diff --git a/.deadcode-out b/.deadcode-out index f71ef41ea2..97093ce93b 100644 --- a/.deadcode-out +++ b/.deadcode-out @@ -50,9 +50,6 @@ forgejo.org/models/organization forgejo.org/models/perm/access GetRepoWriters -forgejo.org/models/repo - WatchRepoMode - forgejo.org/models/user IsErrUserWrongType IsErrExternalLoginUserAlreadyExist @@ -238,6 +235,7 @@ forgejo.org/services/repository forgejo.org/services/repository/files ContentType.String + RepoFileOptionMode forgejo.org/services/repository/gitgraph Parser.Reset diff --git a/.forgejo/cascading-release-end-to-end b/.forgejo/cascading-release-end-to-end index 9be0737b0f..f78c3aeedb 100755 --- a/.forgejo/cascading-release-end-to-end +++ b/.forgejo/cascading-release-end-to-end @@ -2,6 +2,9 @@ set -ex +# WARNING: Changes to the behaviour of this file should be backported to all active releases, as it is used in +# `build-release.yml` from release branches. + end_to_end=$1 end_to_end_pr=$2 forgejo=$3 diff --git a/.forgejo/workflows-composite/install-minimum-git-version/action.yaml b/.forgejo/workflows-composite/install-minimum-git-version/action.yaml index d4e6e3f2a7..ae50d38794 100644 --- a/.forgejo/workflows-composite/install-minimum-git-version/action.yaml +++ b/.forgejo/workflows-composite/install-minimum-git-version/action.yaml @@ -13,7 +13,7 @@ runs: apt-get update -qq apt-get -q install -y -qq curl ca-certificates - curl -sS -o /tmp/git-man.deb http://archive.ubuntu.com/ubuntu/pool/main/g/git/git-man_2.34.1-1ubuntu1_all.deb + curl -sS -o /tmp/git-man.deb https://archive.ubuntu.com/ubuntu/pool/main/g/git/git-man_2.34.1-1ubuntu1_all.deb curl -sS -o /tmp/git.deb https://archive.ubuntu.com/ubuntu/pool/main/g/git/git_2.34.1-1ubuntu1_amd64.deb curl -sS -o /tmp/git-lfs.deb https://archive.ubuntu.com/ubuntu/pool/universe/g/git-lfs/git-lfs_3.0.2-1_amd64.deb diff --git a/.forgejo/workflows-composite/setup-cache-go/action.yaml b/.forgejo/workflows-composite/setup-cache-go/action.yaml index fec166fc35..c44eaf24bd 100644 --- a/.forgejo/workflows-composite/setup-cache-go/action.yaml +++ b/.forgejo/workflows-composite/setup-cache-go/action.yaml @@ -52,10 +52,9 @@ runs: id: cache-deps uses: https://data.forgejo.org/actions/cache@v4 with: - key: setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}-${{ hashFiles('go.sum', 'go.mod') }} + key: setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}-${{ hashFiles('go.sum', 'go.mod', 'Makefile') }} restore-keys: | setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}-${{ steps.go-version.outputs.go_version }}- - setup-cache-go-deps-${{ runner.os }}-${{ inputs.username }}- path: | ${{ steps.go-environment.outputs.modcache }} ${{ steps.go-environment.outputs.cache }} diff --git a/.forgejo/workflows/build-release-integration.yml b/.forgejo/workflows/build-release-integration.yml index aa5e69f64d..d22126bad4 100644 --- a/.forgejo/workflows/build-release-integration.yml +++ b/.forgejo/workflows/build-release-integration.yml @@ -29,7 +29,7 @@ jobs: - uses: https://data.forgejo.org/actions/checkout@v5 - id: forgejo - uses: https://data.forgejo.org/actions/setup-forgejo@v3.0.6 + uses: https://data.forgejo.org/actions/setup-forgejo@v3.1.7 with: user: root password: admin1234 diff --git a/.forgejo/workflows/build-release.yml b/.forgejo/workflows/build-release.yml index 042a981881..f39954af8f 100644 --- a/.forgejo/workflows/build-release.yml +++ b/.forgejo/workflows/build-release.yml @@ -164,7 +164,7 @@ jobs: - name: build container & release if: ${{ secrets.TOKEN != '' }} - uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.4.1 + uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.6.0 with: forgejo: "${{ env.GITHUB_SERVER_URL }}" owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" @@ -183,7 +183,7 @@ jobs: - name: build rootless container if: ${{ secrets.TOKEN != '' }} - uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.4.1 + uses: https://data.forgejo.org/forgejo/forgejo-build-publish/build@v5.6.0 with: forgejo: "${{ env.GITHUB_SERVER_URL }}" owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" @@ -206,7 +206,7 @@ jobs: origin-url: ${{ env.GITHUB_SERVER_URL }} origin-repo: ${{ github.repository }} origin-token: ${{ secrets.CASCADE_ORIGIN_TOKEN }} - origin-ref: refs/heads/forgejo + origin-ref: ${{ github.ref }} destination-url: https://code.forgejo.org destination-fork-repo: ${{ vars.CASCADE_DESTINATION_DOER }}/end-to-end destination-repo: forgejo/end-to-end diff --git a/.forgejo/workflows/publish-release.yml b/.forgejo/workflows/publish-release.yml index a583756656..8eee8e2145 100644 --- a/.forgejo/workflows/publish-release.yml +++ b/.forgejo/workflows/publish-release.yml @@ -44,7 +44,7 @@ jobs: - uses: https://data.forgejo.org/actions/checkout@v5 - name: copy & sign - uses: https://data.forgejo.org/forgejo/forgejo-build-publish/publish@v5.4.1 + uses: https://data.forgejo.org/forgejo/forgejo-build-publish/publish@v5.6.0 with: from-forgejo: ${{ vars.FORGEJO }} to-forgejo: ${{ vars.FORGEJO }} @@ -63,14 +63,14 @@ jobs: - name: get trigger mirror issue id: mirror - uses: https://data.forgejo.org/infrastructure/issue-action/get@v1.3.0 + uses: https://data.forgejo.org/infrastructure/issue-action/get@v1.5.0 with: forgejo: https://code.forgejo.org repository: forgejo/forgejo labels: mirror-trigger - name: trigger the mirror - uses: https://data.forgejo.org/infrastructure/issue-action/set@v1.3.0 + uses: https://data.forgejo.org/infrastructure/issue-action/set@v1.5.0 with: forgejo: https://code.forgejo.org repository: forgejo/forgejo diff --git a/.forgejo/workflows/testing-integration.yml b/.forgejo/workflows/testing-integration.yml index 7c74239f1f..6c690c484f 100644 --- a/.forgejo/workflows/testing-integration.yml +++ b/.forgejo/workflows/testing-integration.yml @@ -31,7 +31,7 @@ jobs: if: vars.ROLE == 'forgejo-integration' runs-on: docker container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime steps: - uses: https://data.forgejo.org/actions/checkout@v5 @@ -50,7 +50,7 @@ jobs: if: vars.ROLE == 'forgejo-integration' runs-on: docker container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime steps: - uses: https://data.forgejo.org/actions/checkout@v5 @@ -75,7 +75,7 @@ jobs: matrix: version: ['10.6', '11.8'] container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime services: mysql: @@ -87,10 +87,10 @@ jobs: steps: - uses: https://data.forgejo.org/actions/checkout@v5 - uses: ./.forgejo/workflows-composite/setup-env - - name: install dependencies & git >= 2.42 - uses: ./.forgejo/workflows-composite/apt-install-from - with: - packages: git git-lfs + - name: install dependencies + run: apt-get update -qq && apt-get -q install -qq -y git-lfs + env: + DEBIAN_FRONTEND: noninteractive - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-mysql-migration test-mysql' diff --git a/.forgejo/workflows/testing.yml b/.forgejo/workflows/testing.yml index 199e616daa..ac9d9f0801 100644 --- a/.forgejo/workflows/testing.yml +++ b/.forgejo/workflows/testing.yml @@ -14,7 +14,7 @@ jobs: if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing' runs-on: docker container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime steps: - name: event info @@ -31,10 +31,13 @@ jobs: if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing' runs-on: docker container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime steps: - uses: https://data.forgejo.org/actions/checkout@v5 + - uses: https://data.forgejo.org/actions/setup-node@v6 + with: + node-version-file: .node-version - run: make deps-frontend - run: make lint-frontend - run: make checks-frontend @@ -60,7 +63,7 @@ jobs: runs-on: docker needs: [backend-checks, frontend-checks] container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime services: elasticsearch: @@ -80,10 +83,6 @@ jobs: steps: - uses: https://data.forgejo.org/actions/checkout@v5 - uses: ./.forgejo/workflows-composite/setup-env - - name: install git >= 2.42 - uses: ./.forgejo/workflows-composite/apt-install-from - with: - packages: git - name: test release-notes-assistant.sh run: | apt-get -q install -qq -y jq @@ -150,7 +149,7 @@ jobs: runs-on: docker needs: [backend-checks, frontend-checks, test-unit] container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime name: ${{ format('test-remote-cacher ({0})', matrix.cacher.name) }} strategy: @@ -177,10 +176,6 @@ jobs: steps: - uses: https://data.forgejo.org/actions/checkout@v5 - uses: ./.forgejo/workflows-composite/setup-env - - name: install git >= 2.42 - uses: ./.forgejo/workflows-composite/apt-install-from - with: - packages: git - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-remote-cacher test-check' @@ -194,7 +189,7 @@ jobs: runs-on: docker needs: [backend-checks, frontend-checks] container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime services: mysql: @@ -210,10 +205,10 @@ jobs: steps: - uses: https://data.forgejo.org/actions/checkout@v5 - uses: ./.forgejo/workflows-composite/setup-env - - name: install dependencies & git >= 2.42 - uses: ./.forgejo/workflows-composite/apt-install-from - with: - packages: git git-lfs + - name: install dependencies + run: apt-get update -qq && apt-get -q install -qq -y git-lfs + env: + DEBIAN_FRONTEND: noninteractive - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-mysql-migration test-mysql' @@ -225,7 +220,7 @@ jobs: runs-on: docker needs: [backend-checks, frontend-checks] container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime services: minio: @@ -248,10 +243,10 @@ jobs: steps: - uses: https://data.forgejo.org/actions/checkout@v5 - uses: ./.forgejo/workflows-composite/setup-env - - name: install dependencies & git >= 2.42 - uses: ./.forgejo/workflows-composite/apt-install-from - with: - packages: git git-lfs + - name: install dependencies + run: apt-get update -qq && apt-get -q install -qq -y git-lfs + env: + DEBIAN_FRONTEND: noninteractive - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-pgsql-migration test-pgsql' @@ -265,15 +260,15 @@ jobs: runs-on: docker needs: [backend-checks, frontend-checks] container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime steps: - uses: https://data.forgejo.org/actions/checkout@v5 - uses: ./.forgejo/workflows-composite/setup-env - - name: install dependencies & git >= 2.42 - uses: ./.forgejo/workflows-composite/apt-install-from - with: - packages: git git-lfs + - name: install dependencies + run: apt-get update -qq && apt-get -q install -qq -y git-lfs + env: + DEBIAN_FRONTEND: noninteractive - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-sqlite-migration test-sqlite' @@ -293,7 +288,7 @@ jobs: - test-remote-cacher - test-unit container: - image: 'data.forgejo.org/oci/node:24-bookworm' + image: 'data.forgejo.org/oci/node:24-trixie' options: --tmpfs /tmp:exec,noatime steps: - uses: https://data.forgejo.org/actions/checkout@v5 diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 6f1e5d5225..5843e169e4 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -219,11 +219,6 @@ "path": "connectrpc.com/connect/LICENSE", "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2021-2025 The Connect Authors\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, - { - "name": "dario.cat/mergo", - "path": "dario.cat/mergo/LICENSE", - "licenseText": "Copyright (c) 2013 Dario Castañé. All rights reserved.\nCopyright (c) 2012 The Go 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 * 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": "filippo.io/edwards25519", "path": "filippo.io/edwards25519/LICENSE", @@ -459,21 +454,6 @@ "path": "github.com/cloudflare/circl/LICENSE", "licenseText": "Copyright (c) 2019 Cloudflare. 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 Cloudflare 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\n========================================================================\n\nCopyright (c) 2009 The Go 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 * 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/cyphar/filepath-securejoin", - "path": "github.com/cyphar/filepath-securejoin/COPYING.md", - "licenseText": "## COPYING ##\n\n`SPDX-License-Identifier: BSD-3-Clause AND MPL-2.0`\n\nThis project is made up of code licensed under different licenses. Which code\nyou use will have an impact on whether only one or both licenses apply to your\nusage of this library.\n\nNote that **each file** in this project individually has a code comment at the\nstart describing the license of that particular file -- this is the most\naccurate license information of this project; in case there is any conflict\nbetween this document and the comment at the start of a file, the comment shall\ntake precedence. The only purpose of this document is to work around [a known\ntechnical limitation of pkg.go.dev's license checking tool when dealing with\nnon-trivial project licenses][go75067].\n\n[go75067]: https://go.dev/issue/75067\n\n### `BSD-3-Clause` ###\n\nAt time of writing, the following files and directories are licensed under the\nBSD-3-Clause license:\n\n * `doc.go`\n * `join*.go`\n * `vfs.go`\n * `internal/consts/*.go`\n * `pathrs-lite/internal/gocompat/*.go`\n * `pathrs-lite/internal/kernelversion/*.go`\n\nThe text of the BSD-3-Clause license used by this project is the following (the\ntext is also available from the [`LICENSE.BSD`](./LICENSE.BSD) file):\n\n```\nCopyright (C) 2014-2015 Docker Inc \u0026 Go Authors. All rights reserved.\nCopyright (C) 2017-2024 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```\n\n### `MPL-2.0` ###\n\nAll other files (unless otherwise marked) are licensed under the Mozilla Public\nLicense (version 2.0).\n\nThe text of the Mozilla Public License (version 2.0) is the following (the text\nis also available from the [`LICENSE.MPL-2.0`](./LICENSE.MPL-2.0) file):\n\n```\nMozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\"\n means each individual or legal entity that creates, contributes to\n the creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n means the combination of the Contributions of others (if any) used\n by a Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n means Source Code Form to which the initial Contributor has attached\n the notice in Exhibit A, the Executable Form of such Source Code\n Form, and Modifications of such Source Code Form, in each case\n including portions thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n means\n\n (a) that the initial Contributor has attached the notice described\n in 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\n terms of a Secondary License.\n\n1.6. \"Executable Form\"\n means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n means a work that combines Covered Software with other material, in\n a separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n means this document.\n\n1.9. \"Licensable\"\n means having the right to grant, to the maximum extent possible,\n whether at the time of the initial grant or subsequently, any and\n all of the rights conveyed by this License.\n\n1.10. \"Modifications\"\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\n Software; or\n\n (b) any new file in Source Code Form that contains any Covered\n Software.\n\n1.11. \"Patent Claims\" of a Contributor\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\n License, by the making, using, selling, offering for sale, having\n made, import, or transfer of either its Contributions or its\n Contributor Version.\n\n1.12. \"Secondary License\"\n means either the GNU General Public License, Version 2.0, the GNU\n Lesser General Public License, Version 2.1, the GNU Affero General\n Public License, Version 3.0, or any later versions of those\n licenses.\n\n1.13. \"Source Code Form\"\n means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n means an individual or a legal entity exercising rights under this\n License. For legal entities, \"You\" includes any entity that\n controls, is controlled by, or is under common control with You. For\n purposes of this definition, \"control\" means (a) the power, direct\n or indirect, to cause the direction or management of such entity,\n whether by contract or otherwise, or (b) ownership of more than\n fifty percent (50%) of the outstanding shares or beneficial\n ownership of such entity.\n\n2. License Grants and Conditions\n--------------------------------\n\n2.1. Grants\n\nEach Contributor hereby grants You a world-wide, royalty-free,\nnon-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\n for sale, have made, import, and otherwise transfer either its\n Contributions or its Contributor Version.\n\n2.2. Effective Date\n\nThe licenses granted in Section 2.1 with respect to any Contribution\nbecome effective for each Contribution on the date the Contributor first\ndistributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\nThe licenses granted in this Section 2 are the only rights granted under\nthis License. No additional rights or licenses will be implied from the\ndistribution or licensing of Covered Software under this License.\nNotwithstanding Section 2.1(b) above, no patent license is granted by a\nContributor:\n\n(a) for any code that a Contributor has removed from Covered Software;\n 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\nThis License does not grant any rights in the trademarks, service marks,\nor logos of any Contributor (except as may be necessary to comply with\nthe notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\nNo Contributor makes additional grants as a result of Your choice to\ndistribute the Covered Software under a subsequent version of this\nLicense (see Section 10.2) or under the terms of a Secondary License (if\npermitted under the terms of Section 3.3).\n\n2.5. Representation\n\nEach Contributor represents that the Contributor believes its\nContributions are its original creation(s) or it has sufficient rights\nto grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\nThis License is not intended to limit any rights You have under\napplicable copyright doctrines of fair use, fair dealing, or other\nequivalents.\n\n2.7. Conditions\n\nSections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\nin Section 2.1.\n\n3. Responsibilities\n-------------------\n\n3.1. Distribution of Source Form\n\nAll distribution of Covered Software in Source Code Form, including any\nModifications that You create or to which You contribute, must be under\nthe terms of this License. You must inform recipients that the Source\nCode Form of the Covered Software is governed by the terms of this\nLicense, and how they can obtain a copy of this License. You may not\nattempt to alter or restrict the recipients' rights in the Source Code\nForm.\n\n3.2. Distribution of Executable Form\n\nIf You distribute Covered Software in Executable Form then:\n\n(a) such Covered Software must also be made available in Source Code\n Form, as described in Section 3.1, and You must inform recipients of\n the Executable Form how they can obtain a copy of such Source Code\n Form by reasonable means in a timely manner, at a charge no more\n than the cost 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\n the recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\nYou may create and distribute a Larger Work under terms of Your choice,\nprovided that You also comply with the requirements of this License for\nthe Covered Software. If the Larger Work is a combination of Covered\nSoftware with a work governed by one or more Secondary Licenses, and the\nCovered Software is not Incompatible With Secondary Licenses, this\nLicense permits You to additionally distribute such Covered Software\nunder the terms of such Secondary License(s), so that the recipient of\nthe Larger Work may, at their option, further distribute the Covered\nSoftware under the terms of either this License or such Secondary\nLicense(s).\n\n3.4. Notices\n\nYou may not remove or alter the substance of any license notices\n(including copyright notices, patent notices, disclaimers of warranty,\nor limitations of liability) contained within the Source Code Form of\nthe Covered Software, except that You may alter any license notices to\nthe extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\nYou may choose to offer, and to charge a fee for, warranty, support,\nindemnity or liability obligations to one or more recipients of Covered\nSoftware. However, You may do so only on Your own behalf, and not on\nbehalf of any Contributor. You must make it absolutely clear that any\nsuch warranty, support, indemnity, or liability obligation is offered by\nYou alone, and You hereby agree to indemnify every Contributor for any\nliability incurred by such Contributor as a result of warranty, support,\nindemnity or liability terms You offer. You may include additional\ndisclaimers of warranty and limitations of liability specific to any\njurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n---------------------------------------------------\n\nIf it is impossible for You to comply with any of the terms of this\nLicense with respect to some or all of the Covered Software due to\nstatute, judicial order, or regulation then You must: (a) comply with\nthe terms of this License to the maximum extent possible; and (b)\ndescribe the limitations and the code they affect. Such description must\nbe placed in a text file included with all distributions of the Covered\nSoftware under this License. Except to the extent prohibited by statute\nor regulation, such description must be sufficiently detailed for a\nrecipient of ordinary skill to be able to understand it.\n\n5. Termination\n--------------\n\n5.1. The rights granted under this License will terminate automatically\nif You fail to comply with any of its terms. However, if You become\ncompliant, then the rights granted under this License from a particular\nContributor are reinstated (a) provisionally, unless and until such\nContributor explicitly and finally terminates Your grants, and (b) on an\nongoing basis, if such Contributor fails to notify You of the\nnon-compliance by some reasonable means prior to 60 days after You have\ncome back into compliance. Moreover, Your grants from a particular\nContributor are reinstated on an ongoing basis if such Contributor\nnotifies You of the non-compliance by some reasonable means, this is the\nfirst time You have received notice of non-compliance with this License\nfrom such Contributor, and You become compliant prior to 30 days after\nYour receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\ninfringement claim (excluding declaratory judgment actions,\ncounter-claims, and cross-claims) alleging that a Contributor Version\ndirectly or indirectly infringes any patent, then the rights granted to\nYou by any and all Contributors for the Covered Software under Section\n2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all\nend user license agreements (excluding distributors and resellers) which\nhave been validly granted by You or Your distributors under this License\nprior to termination shall survive termination.\n\n************************************************************************\n* *\n* 6. Disclaimer of Warranty *\n* ------------------------- *\n* *\n* Covered Software is provided under this License on an \"as is\" *\n* basis, without warranty of any kind, either expressed, implied, or *\n* statutory, including, without limitation, warranties that the *\n* Covered Software is free of defects, merchantable, fit for a *\n* particular purpose or non-infringing. The entire risk as to the *\n* quality and performance of the Covered Software is with You. *\n* Should any Covered Software prove defective in any respect, You *\n* (not any Contributor) assume the cost of any necessary servicing, *\n* repair, or correction. This disclaimer of warranty constitutes an *\n* essential part of this License. No use of any Covered Software is *\n* authorized under this License except under this disclaimer. *\n* *\n************************************************************************\n\n************************************************************************\n* *\n* 7. Limitation of Liability *\n* -------------------------- *\n* *\n* Under no circumstances and under no legal theory, whether tort *\n* (including negligence), contract, or otherwise, shall any *\n* Contributor, or anyone who distributes Covered Software as *\n* permitted above, be liable to You for any direct, indirect, *\n* special, incidental, or consequential damages of any character *\n* including, without limitation, damages for lost profits, loss of *\n* goodwill, work stoppage, computer failure or malfunction, or any *\n* and all other commercial damages or losses, even if such party *\n* shall have been informed of the possibility of such damages. This *\n* limitation of liability shall not apply to liability for death or *\n* personal injury resulting from such party's negligence to the *\n* extent applicable law prohibits such limitation. Some *\n* jurisdictions do not allow the exclusion or limitation of *\n* incidental or consequential damages, so this exclusion and *\n* limitation may not apply to You. *\n* *\n************************************************************************\n\n8. Litigation\n-------------\n\nAny litigation relating to this License may be brought only in the\ncourts of a jurisdiction where the defendant maintains its principal\nplace of business and such litigation shall be governed by laws of that\njurisdiction, without reference to its conflict-of-law provisions.\nNothing in this Section shall prevent a party's ability to bring\ncross-claims or counter-claims.\n\n9. Miscellaneous\n----------------\n\nThis License represents the complete agreement concerning the subject\nmatter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent\nnecessary to make it enforceable. Any law or regulation which provides\nthat the language of a contract shall be construed against the drafter\nshall not be used to construe this License against a Contributor.\n\n10. Versions of the License\n---------------------------\n\n10.1. New Versions\n\nMozilla Foundation is the license steward. Except as provided in Section\n10.3, no one other than the license steward has the right to modify or\npublish new versions of this License. Each version will be given a\ndistinguishing version number.\n\n10.2. Effect of New Versions\n\nYou may distribute the Covered Software under the terms of the version\nof the License under which You originally received the Covered Software,\nor under the terms of any subsequent version published by the license\nsteward.\n\n10.3. Modified Versions\n\nIf you create software not governed by this License, and you want to\ncreate a new license for such software, you may create and use a\nmodified version of this License if you rename the license and remove\nany references to the name of the license steward (except to note that\nsuch modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\nLicenses\n\nIf You choose to distribute Source Code Form that is Incompatible With\nSecondary Licenses under the terms of this version of the License, the\nnotice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n-------------------------------------------\n\n This Source Code Form is subject to the terms of the Mozilla Public\n License, v. 2.0. If a copy of the MPL was not distributed with this\n file, You can obtain one at https://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular\nfile, then You may include the notice in a location (such as a LICENSE\nfile in a relevant directory) where a recipient would be likely to look\nfor such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n---------------------------------------------------------\n\n This Source Code Form is \"Incompatible With Secondary Licenses\", as\n defined by the Mozilla Public License, v. 2.0.\n```\n" - }, - { - "name": "github.com/cyphar/filepath-securejoin", - "path": "github.com/cyphar/filepath-securejoin/LICENSE.BSD", - "licenseText": "Copyright (C) 2014-2015 Docker Inc \u0026 Go Authors. All rights reserved.\nCopyright (C) 2017-2024 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/cyphar/filepath-securejoin", - "path": "github.com/cyphar/filepath-securejoin/LICENSE.MPL-2.0", - "licenseText": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\"\n means each individual or legal entity that creates, contributes to\n the creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n means the combination of the Contributions of others (if any) used\n by a Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n means Source Code Form to which the initial Contributor has attached\n the notice in Exhibit A, the Executable Form of such Source Code\n Form, and Modifications of such Source Code Form, in each case\n including portions thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n means\n\n (a) that the initial Contributor has attached the notice described\n in 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\n terms of a Secondary License.\n\n1.6. \"Executable Form\"\n means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n means a work that combines Covered Software with other material, in\n a separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n means this document.\n\n1.9. \"Licensable\"\n means having the right to grant, to the maximum extent possible,\n whether at the time of the initial grant or subsequently, any and\n all of the rights conveyed by this License.\n\n1.10. \"Modifications\"\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\n Software; or\n\n (b) any new file in Source Code Form that contains any Covered\n Software.\n\n1.11. \"Patent Claims\" of a Contributor\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\n License, by the making, using, selling, offering for sale, having\n made, import, or transfer of either its Contributions or its\n Contributor Version.\n\n1.12. \"Secondary License\"\n means either the GNU General Public License, Version 2.0, the GNU\n Lesser General Public License, Version 2.1, the GNU Affero General\n Public License, Version 3.0, or any later versions of those\n licenses.\n\n1.13. \"Source Code Form\"\n means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n means an individual or a legal entity exercising rights under this\n License. For legal entities, \"You\" includes any entity that\n controls, is controlled by, or is under common control with You. For\n purposes of this definition, \"control\" means (a) the power, direct\n or indirect, to cause the direction or management of such entity,\n whether by contract or otherwise, or (b) ownership of more than\n fifty percent (50%) of the outstanding shares or beneficial\n ownership of such entity.\n\n2. License Grants and Conditions\n--------------------------------\n\n2.1. Grants\n\nEach Contributor hereby grants You a world-wide, royalty-free,\nnon-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\n for sale, have made, import, and otherwise transfer either its\n Contributions or its Contributor Version.\n\n2.2. Effective Date\n\nThe licenses granted in Section 2.1 with respect to any Contribution\nbecome effective for each Contribution on the date the Contributor first\ndistributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\nThe licenses granted in this Section 2 are the only rights granted under\nthis License. No additional rights or licenses will be implied from the\ndistribution or licensing of Covered Software under this License.\nNotwithstanding Section 2.1(b) above, no patent license is granted by a\nContributor:\n\n(a) for any code that a Contributor has removed from Covered Software;\n 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\nThis License does not grant any rights in the trademarks, service marks,\nor logos of any Contributor (except as may be necessary to comply with\nthe notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\nNo Contributor makes additional grants as a result of Your choice to\ndistribute the Covered Software under a subsequent version of this\nLicense (see Section 10.2) or under the terms of a Secondary License (if\npermitted under the terms of Section 3.3).\n\n2.5. Representation\n\nEach Contributor represents that the Contributor believes its\nContributions are its original creation(s) or it has sufficient rights\nto grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\nThis License is not intended to limit any rights You have under\napplicable copyright doctrines of fair use, fair dealing, or other\nequivalents.\n\n2.7. Conditions\n\nSections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\nin Section 2.1.\n\n3. Responsibilities\n-------------------\n\n3.1. Distribution of Source Form\n\nAll distribution of Covered Software in Source Code Form, including any\nModifications that You create or to which You contribute, must be under\nthe terms of this License. You must inform recipients that the Source\nCode Form of the Covered Software is governed by the terms of this\nLicense, and how they can obtain a copy of this License. You may not\nattempt to alter or restrict the recipients' rights in the Source Code\nForm.\n\n3.2. Distribution of Executable Form\n\nIf You distribute Covered Software in Executable Form then:\n\n(a) such Covered Software must also be made available in Source Code\n Form, as described in Section 3.1, and You must inform recipients of\n the Executable Form how they can obtain a copy of such Source Code\n Form by reasonable means in a timely manner, at a charge no more\n than the cost 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\n the recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\nYou may create and distribute a Larger Work under terms of Your choice,\nprovided that You also comply with the requirements of this License for\nthe Covered Software. If the Larger Work is a combination of Covered\nSoftware with a work governed by one or more Secondary Licenses, and the\nCovered Software is not Incompatible With Secondary Licenses, this\nLicense permits You to additionally distribute such Covered Software\nunder the terms of such Secondary License(s), so that the recipient of\nthe Larger Work may, at their option, further distribute the Covered\nSoftware under the terms of either this License or such Secondary\nLicense(s).\n\n3.4. Notices\n\nYou may not remove or alter the substance of any license notices\n(including copyright notices, patent notices, disclaimers of warranty,\nor limitations of liability) contained within the Source Code Form of\nthe Covered Software, except that You may alter any license notices to\nthe extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\nYou may choose to offer, and to charge a fee for, warranty, support,\nindemnity or liability obligations to one or more recipients of Covered\nSoftware. However, You may do so only on Your own behalf, and not on\nbehalf of any Contributor. You must make it absolutely clear that any\nsuch warranty, support, indemnity, or liability obligation is offered by\nYou alone, and You hereby agree to indemnify every Contributor for any\nliability incurred by such Contributor as a result of warranty, support,\nindemnity or liability terms You offer. You may include additional\ndisclaimers of warranty and limitations of liability specific to any\njurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n---------------------------------------------------\n\nIf it is impossible for You to comply with any of the terms of this\nLicense with respect to some or all of the Covered Software due to\nstatute, judicial order, or regulation then You must: (a) comply with\nthe terms of this License to the maximum extent possible; and (b)\ndescribe the limitations and the code they affect. Such description must\nbe placed in a text file included with all distributions of the Covered\nSoftware under this License. Except to the extent prohibited by statute\nor regulation, such description must be sufficiently detailed for a\nrecipient of ordinary skill to be able to understand it.\n\n5. Termination\n--------------\n\n5.1. The rights granted under this License will terminate automatically\nif You fail to comply with any of its terms. However, if You become\ncompliant, then the rights granted under this License from a particular\nContributor are reinstated (a) provisionally, unless and until such\nContributor explicitly and finally terminates Your grants, and (b) on an\nongoing basis, if such Contributor fails to notify You of the\nnon-compliance by some reasonable means prior to 60 days after You have\ncome back into compliance. Moreover, Your grants from a particular\nContributor are reinstated on an ongoing basis if such Contributor\nnotifies You of the non-compliance by some reasonable means, this is the\nfirst time You have received notice of non-compliance with this License\nfrom such Contributor, and You become compliant prior to 30 days after\nYour receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\ninfringement claim (excluding declaratory judgment actions,\ncounter-claims, and cross-claims) alleging that a Contributor Version\ndirectly or indirectly infringes any patent, then the rights granted to\nYou by any and all Contributors for the Covered Software under Section\n2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all\nend user license agreements (excluding distributors and resellers) which\nhave been validly granted by You or Your distributors under this License\nprior to termination shall survive termination.\n\n************************************************************************\n* *\n* 6. Disclaimer of Warranty *\n* ------------------------- *\n* *\n* Covered Software is provided under this License on an \"as is\" *\n* basis, without warranty of any kind, either expressed, implied, or *\n* statutory, including, without limitation, warranties that the *\n* Covered Software is free of defects, merchantable, fit for a *\n* particular purpose or non-infringing. The entire risk as to the *\n* quality and performance of the Covered Software is with You. *\n* Should any Covered Software prove defective in any respect, You *\n* (not any Contributor) assume the cost of any necessary servicing, *\n* repair, or correction. This disclaimer of warranty constitutes an *\n* essential part of this License. No use of any Covered Software is *\n* authorized under this License except under this disclaimer. *\n* *\n************************************************************************\n\n************************************************************************\n* *\n* 7. Limitation of Liability *\n* -------------------------- *\n* *\n* Under no circumstances and under no legal theory, whether tort *\n* (including negligence), contract, or otherwise, shall any *\n* Contributor, or anyone who distributes Covered Software as *\n* permitted above, be liable to You for any direct, indirect, *\n* special, incidental, or consequential damages of any character *\n* including, without limitation, damages for lost profits, loss of *\n* goodwill, work stoppage, computer failure or malfunction, or any *\n* and all other commercial damages or losses, even if such party *\n* shall have been informed of the possibility of such damages. This *\n* limitation of liability shall not apply to liability for death or *\n* personal injury resulting from such party's negligence to the *\n* extent applicable law prohibits such limitation. Some *\n* jurisdictions do not allow the exclusion or limitation of *\n* incidental or consequential damages, so this exclusion and *\n* limitation may not apply to You. *\n* *\n************************************************************************\n\n8. Litigation\n-------------\n\nAny litigation relating to this License may be brought only in the\ncourts of a jurisdiction where the defendant maintains its principal\nplace of business and such litigation shall be governed by laws of that\njurisdiction, without reference to its conflict-of-law provisions.\nNothing in this Section shall prevent a party's ability to bring\ncross-claims or counter-claims.\n\n9. Miscellaneous\n----------------\n\nThis License represents the complete agreement concerning the subject\nmatter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent\nnecessary to make it enforceable. Any law or regulation which provides\nthat the language of a contract shall be construed against the drafter\nshall not be used to construe this License against a Contributor.\n\n10. Versions of the License\n---------------------------\n\n10.1. New Versions\n\nMozilla Foundation is the license steward. Except as provided in Section\n10.3, no one other than the license steward has the right to modify or\npublish new versions of this License. Each version will be given a\ndistinguishing version number.\n\n10.2. Effect of New Versions\n\nYou may distribute the Covered Software under the terms of the version\nof the License under which You originally received the Covered Software,\nor under the terms of any subsequent version published by the license\nsteward.\n\n10.3. Modified Versions\n\nIf you create software not governed by this License, and you want to\ncreate a new license for such software, you may create and use a\nmodified version of this License if you rename the license and remove\nany references to the name of the license steward (except to note that\nsuch modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\nLicenses\n\nIf You choose to distribute Source Code Form that is Incompatible With\nSecondary Licenses under the terms of this version of the License, the\nnotice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n-------------------------------------------\n\n This Source Code Form is subject to the terms of the Mozilla Public\n License, v. 2.0. If a copy of the MPL was not distributed with this\n file, You can obtain one at https://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular\nfile, then You may include the notice in a location (such as a LICENSE\nfile in a relevant directory) where a recipient would be likely to look\nfor such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n---------------------------------------------------------\n\n This Source Code Form is \"Incompatible With Secondary Licenses\", as\n defined by the Mozilla Public License, v. 2.0.\n" - }, { "name": "github.com/davecgh/go-spew/spew", "path": "github.com/davecgh/go-spew/spew/LICENSE", @@ -549,11 +529,6 @@ "path": "github.com/emersion/go-sasl/LICENSE", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2016 emersion\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/emirpasic/gods", - "path": "github.com/emirpasic/gods/LICENSE", - "licenseText": "Copyright (c) 2015, Emir Pasic\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (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\n-------------------------------------------------------------------------------\n\nAVL Tree:\n\nCopyright (c) 2017 Benjamin Scher Purcell \u003cbenjapurcell@gmail.com\u003e\n\nPermission to use, copy, modify, and distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n" - }, { "name": "github.com/fatih/color", "path": "github.com/fatih/color/LICENSE.md", @@ -709,11 +684,6 @@ "path": "github.com/golang/geo/LICENSE", "licenseText": "\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, - { - "name": "github.com/golang/groupcache/lru", - "path": "github.com/golang/groupcache/lru/LICENSE", - "licenseText": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and\ndistribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright\nowner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities\nthat control, are controlled by, or are under common control with that entity.\nFor the purposes of this definition, \"control\" means (i) the power, direct or\nindirect, to cause the direction or management of such entity, whether by\ncontract or otherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising\npermissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including\nbut not limited to software source code, documentation source, and configuration\nfiles.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or\ntranslation of a Source form, including but not limited to compiled object code,\ngenerated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made\navailable under the License, as indicated by a copyright notice that is included\nin or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that\nis based on (or derived from) the Work and for which the editorial revisions,\nannotations, elaborations, or other modifications represent, as a whole, an\noriginal work of authorship. For the purposes of this License, Derivative Works\nshall not include works that remain separable from, or merely link (or bind by\nname) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version\nof the Work and any modifications or additions to that Work or Derivative Works\nthereof, that is intentionally submitted to Licensor for inclusion in the Work\nby the copyright owner or by an individual or Legal Entity authorized to submit\non behalf of the copyright owner. For the purposes of this definition,\n\"submitted\" means any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems, and\nissue tracking systems that are managed by, or on behalf of, the Licensor for\nthe purpose of discussing and improving the Work, but excluding communication\nthat is conspicuously marked or otherwise designated in writing by the copyright\nowner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf\nof whom a Contribution has been received by Licensor and subsequently\nincorporated within the Work.\n\n2. Grant of Copyright License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable copyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the Work and such\nDerivative Works in Source or Object form.\n\n3. Grant of Patent License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable (except as stated in this section) patent license to make, have\nmade, use, offer to sell, sell, import, and otherwise transfer the Work, where\nsuch license applies only to those patent claims licensable by such Contributor\nthat are necessarily infringed by their Contribution(s) alone or by combination\nof their Contribution(s) with the Work to which such Contribution(s) was\nsubmitted. If You institute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work or a\nContribution incorporated within the Work constitutes direct or contributory\npatent infringement, then any patent licenses granted to You under this License\nfor that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution.\n\nYou may reproduce and distribute copies of the Work or Derivative Works thereof\nin any medium, with or without modifications, and in Source or Object form,\nprovided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of\nthis License; and\nYou must cause any modified files to carry prominent notices stating that You\nchanged the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute,\nall copyright, patent, trademark, and attribution notices from the Source form\nof the Work, excluding those notices that do not pertain to any part of the\nDerivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any\nDerivative Works that You distribute must include a readable copy of the\nattribution notices contained within such NOTICE file, excluding those notices\nthat do not pertain to any part of the Derivative Works, in at least one of the\nfollowing places: within a NOTICE text file distributed as part of the\nDerivative Works; within the Source form or documentation, if provided along\nwith the Derivative Works; or, within a display generated by the Derivative\nWorks, if and wherever such third-party notices normally appear. The contents of\nthe NOTICE file are for informational purposes only and do not modify the\nLicense. You may add Your own attribution notices within Derivative Works that\nYou distribute, alongside or as an addendum to the NOTICE text from the Work,\nprovided that such additional attribution notices cannot be construed as\nmodifying the License.\nYou may add Your own copyright statement to Your modifications and may provide\nadditional or different license terms and conditions for use, reproduction, or\ndistribution of Your modifications, or for any such Derivative Works as a whole,\nprovided Your use, reproduction, and distribution of the Work otherwise complies\nwith the conditions stated in this License.\n\n5. Submission of Contributions.\n\nUnless You explicitly state otherwise, any Contribution intentionally submitted\nfor inclusion in the Work by You to the Licensor shall be under the terms and\nconditions of this License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify the terms of\nany separate license agreement you may have executed with Licensor regarding\nsuch Contributions.\n\n6. Trademarks.\n\nThis License does not grant permission to use the trade names, trademarks,\nservice marks, or product names of the Licensor, except as required for\nreasonable and customary use in describing the origin of the Work and\nreproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty.\n\nUnless required by applicable law or agreed to in writing, Licensor provides the\nWork (and each Contributor provides its Contributions) on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,\nincluding, without limitation, any warranties or conditions of TITLE,\nNON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are\nsolely responsible for determining the appropriateness of using or\nredistributing the Work and assume any risks associated with Your exercise of\npermissions under this License.\n\n8. Limitation of Liability.\n\nIn no event and under no legal theory, whether in tort (including negligence),\ncontract, or otherwise, unless required by applicable law (such as deliberate\nand grossly negligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special, incidental,\nor consequential damages of any character arising as a result of this License or\nout of the use or inability to use the Work (including but not limited to\ndamages for loss of goodwill, work stoppage, computer failure or malfunction, or\nany and all other commercial damages or losses), even if such Contributor has\nbeen advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability.\n\nWhile redistributing the Work or Derivative Works thereof, You may choose to\noffer, and charge a fee for, acceptance of support, warranty, indemnity, or\nother liability obligations and/or rights consistent with this License. However,\nin accepting such obligations, You may act only on Your own behalf and on Your\nsole responsibility, not on behalf of any other Contributor, and only if You\nagree to indemnify, defend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason of your\naccepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work\n\nTo apply the Apache License to your work, attach the following boilerplate\nnotice, with the fields enclosed by brackets \"[]\" replaced with your own\nidentifying information. (Don't include the brackets!) The text should be\nenclosed in the appropriate comment syntax for the file format. We also\nrecommend that a file or class name and description of purpose be included on\nthe same \"printed page\" as the copyright notice for easier identification within\nthird-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" - }, { "name": "github.com/golang/snappy", "path": "github.com/golang/snappy/LICENSE", @@ -730,8 +700,8 @@ "licenseText": "Copyright (c) 2017 The Go 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 * 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/google/go-github/v74/github", - "path": "github.com/google/go-github/v74/github/LICENSE", + "name": "github.com/google/go-github/v81/github", + "path": "github.com/google/go-github/v81/github/LICENSE", "licenseText": "Copyright (c) 2013 The go-github 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 * 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" }, { @@ -859,11 +829,6 @@ "path": "github.com/kballard/go-shellquote/LICENSE", "licenseText": "Copyright (C) 2014 Kevin Ballard\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the \"Software\"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE\nOR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" }, - { - "name": "github.com/kevinburke/ssh_config", - "path": "github.com/kevinburke/ssh_config/LICENSE", - "licenseText": "Copyright (c) 2017 Kevin Burke.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n===================\n\nThe lexer and parser borrow heavily from github.com/pelletier/go-toml. The\nlicense for that project is copied below.\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton\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/klauspost/compress", "path": "github.com/klauspost/compress/LICENSE", @@ -901,8 +866,8 @@ }, { "name": "github.com/lib/pq", - "path": "github.com/lib/pq/LICENSE.md", - "licenseText": "Copyright (c) 2011-2013, 'pq' Contributors\nPortions Copyright (C) 2011 Blake Mizerany\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" + "path": "github.com/lib/pq/LICENSE", + "licenseText": "MIT License\n\nCopyright (c) 2011-2013, 'pq' Contributors. Portions Copyright (c) 2011 Blake Mizerany\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/libdns/libdns", @@ -1069,11 +1034,6 @@ "path": "github.com/pierrec/lz4/v4/LICENSE", "licenseText": "Copyright (c) 2015, Pierre Curto\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of xxHash nor the names of its\n contributors may be used to endorse or promote products derived from\n this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (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\n" }, - { - "name": "github.com/pjbgf/sha1cd", - "path": "github.com/pjbgf/sha1cd/LICENSE", - "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2023 pjbgf\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" - }, { "name": "github.com/pkg/errors", "path": "github.com/pkg/errors/LICENSE", @@ -1154,11 +1114,6 @@ "path": "github.com/sirupsen/logrus/LICENSE", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2014 Simon Eskildsen\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\nall copies 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\nTHE SOFTWARE.\n" }, - { - "name": "github.com/skeema/knownhosts", - "path": "github.com/skeema/knownhosts/LICENSE", - "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"{}\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright {yyyy} {name of copyright owner}\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" - }, { "name": "github.com/sorairolake/lzip-go", "path": "github.com/sorairolake/lzip-go/LICENSE-APACHE", @@ -1209,11 +1164,6 @@ "path": "github.com/x448/float16/LICENSE", "licenseText": "MIT License\n\nCopyright (c) 2019 Montgomery Edwards⁴⁴⁸ and Faye Amacker\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\n" }, - { - "name": "github.com/xanzy/ssh-agent", - "path": "github.com/xanzy/ssh-agent/LICENSE", - "licenseText": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"{}\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright {yyyy} {name of copyright owner}\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n" - }, { "name": "github.com/yohcop/openid-go", "path": "github.com/yohcop/openid-go/LICENSE", @@ -1272,7 +1222,7 @@ { "name": "go.yaml.in/yaml/v4", "path": "go.yaml.in/yaml/v4/LICENSE", - "licenseText": "\nThis project is covered by two different licenses: MIT and Apache.\n\n#### MIT License ####\n\nThe following files were ported to Go from C files of libyaml, and thus\nare still covered by their original MIT license, with the additional\ncopyright staring in 2011 when the project was ported over:\n\n apic.go emitterc.go parserc.go readerc.go scannerc.go\n writerc.go yamlh.go yamlprivateh.go\n\nCopyright (c) 2006-2010 Kirill Simonov\nCopyright (c) 2006-2011 Kirill Simonov\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\nof the Software, and to permit persons to whom the Software is furnished to do\nso, 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\n### Apache License ###\n\nAll the remaining project files are covered by the Apache license:\n\nCopyright (c) 2011-2019 Canonical Ltd\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n" + "licenseText": "\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright 2025 - The go-yaml Project Contributors\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, { "name": "go4.org/readerutil", diff --git a/build/lint-locale-usage/handle-tmpl.go b/build/lint-locale-usage/handle-tmpl.go index e8d4832f9d..8d03291205 100644 --- a/build/lint-locale-usage/handle-tmpl.go +++ b/build/lint-locale-usage/handle-tmpl.go @@ -73,12 +73,6 @@ func (handler Handler) handleTemplateNode(fset *token.FileSet, node tmplParser.N funcname = nodeVar.Ident[2] } - if funcname == "IterWithTr" { - for i := 2; i < len(nodeCommand.Args); i += 2 { - handler.handleTemplateMsgid(fset, nodeCommand.Args[i]) - } - } - var gotUnexpectedInvoke *int ltf, ok := handler.LocaleTrFunctions[funcname] if !ok { diff --git a/cmd/admin.go b/cmd/admin.go index 90157e2d5a..60b25eb971 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -64,6 +64,8 @@ func subcmdAuth() *cli.Command { microcmdAuthUpdateLdapBindDn(), microcmdAuthAddLdapSimpleAuth(), microcmdAuthUpdateLdapSimpleAuth(), + microcmdAuthAddPAM(), + microcmdAuthUpdatePAM(), microcmdAuthAddSMTP(), microcmdAuthUpdateSMTP(), microcmdAuthList(), diff --git a/cmd/admin_auth_pam.go b/cmd/admin_auth_pam.go new file mode 100644 index 0000000000..25e32503e0 --- /dev/null +++ b/cmd/admin_auth_pam.go @@ -0,0 +1,145 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package cmd + +import ( + "context" + "errors" + + auth_model "forgejo.org/models/auth" + "forgejo.org/services/auth/source/pam" + + "github.com/urfave/cli/v3" +) + +func pamCLIFlags() []cli.Flag { + return []cli.Flag{ + &cli.StringFlag{ + Name: "name", + Value: "", + Usage: "Application Name", + }, + &cli.StringFlag{ + Name: "service-name", + Value: "PLAIN", + Usage: "PAM service name", + }, + &cli.StringFlag{ + Name: "email-domain", + Value: "", + Usage: "PAM email domain", + }, + &cli.BoolFlag{ + Name: "skip-local-2fa", + Usage: "Skip 2FA to log on.", + Value: true, + }, + &cli.BoolFlag{ + Name: "active", + Usage: "This Authentication Source is Activated.", + Value: true, + }, + } +} + +func microcmdAuthAddPAM() *cli.Command { + return &cli.Command{ + Name: "add-pam", + Usage: "Add new PAM authentication source", + Before: noDanglingArgs, + Action: newAuthService().addPAM, + Flags: pamCLIFlags(), + } +} + +func microcmdAuthUpdatePAM() *cli.Command { + return &cli.Command{ + Name: "update-pam", + Usage: "Update existing PAM authentication source", + Before: noDanglingArgs, + Action: newAuthService().updatePAM, + Flags: append(pamCLIFlags()[:1], append([]cli.Flag{idFlag()}, pamCLIFlags()[1:]...)...), + } +} + +func parsePAMConfig(_ context.Context, c *cli.Command) *pam.Source { + return &pam.Source{ + ServiceName: c.String("service-name"), + EmailDomain: c.String("email-domain"), + SkipLocalTwoFA: c.Bool("skip-local-2fa"), + } +} + +func (a *authService) addPAM(ctx context.Context, c *cli.Command) error { + ctx, cancel := installSignals(ctx) + defer cancel() + + if err := a.initDB(ctx); err != nil { + return err + } + + if !c.IsSet("name") || len(c.String("name")) == 0 { + return errors.New("name must be set") + } + if !c.IsSet("service-name") || len(c.String("service-name")) == 0 { + return errors.New("service-name must be set") + } + active := true + if c.IsSet("active") { + active = c.Bool("active") + } + + config := parsePAMConfig(ctx, c) + + return a.createAuthSource(ctx, &auth_model.Source{ + Type: auth_model.PAM, + Name: c.String("name"), + IsActive: active, + Cfg: config, + }) +} + +func (a *authService) updatePAM(ctx context.Context, c *cli.Command) error { + if !c.IsSet("id") { + return errors.New("--id flag is missing") + } + + ctx, cancel := installSignals(ctx) + defer cancel() + + if err := a.initDB(ctx); err != nil { + return err + } + + source, err := a.getAuthSource(ctx, c, auth_model.PAM) + if err != nil { + return err + } + + pamConfig := source.Cfg.(*pam.Source) + + if c.IsSet("name") { + source.Name = c.String("name") + } + + if c.IsSet("service-name") { + pamConfig.ServiceName = c.String("service-name") + } + + if c.IsSet("email-domain") { + pamConfig.EmailDomain = c.String("email-domain") + } + + if c.IsSet("skip-local-2fa") { + pamConfig.SkipLocalTwoFA = c.Bool("skip-local-2fa") + } + + if c.IsSet("active") { + source.IsActive = c.Bool("active") + } + + source.Cfg = pamConfig + + return a.updateAuthSource(ctx, source) +} diff --git a/cmd/admin_auth_pam_test.go b/cmd/admin_auth_pam_test.go new file mode 100644 index 0000000000..d14dfe790b --- /dev/null +++ b/cmd/admin_auth_pam_test.go @@ -0,0 +1,293 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package cmd + +import ( + "context" + "testing" + + "forgejo.org/models/auth" + "forgejo.org/modules/test" + "forgejo.org/services/auth/source/pam" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v3" +) + +func TestPamService(t *testing.T) { + // Mock cli functions to do not exit on error + defer test.MockVariableValue(&cli.OsExiter, func(code int) {})() + + // Test cases + cases := []struct { + args []string + source *auth.Source + errMsg string + }{ + // case 0 + { + args: []string{ + "pam-test", + "--name", "Pam Service", + "--service-name", "myservice", + }, + source: &auth.Source{ + Type: auth.PAM, + Name: "Pam Service", + IsActive: true, + Cfg: &pam.Source{ + ServiceName: "myservice", + EmailDomain: "", + SkipLocalTwoFA: true, + }, + }, + }, + // case 1 + { + args: []string{ + "pam-test", + "--name", "Pam Service", + "--service-name", "myservice", + "--email-domain", "testdomain.org", + "--skip-local-2fa", + }, + source: &auth.Source{ + Type: auth.PAM, + Name: "Pam Service", + IsActive: true, + Cfg: &pam.Source{ + ServiceName: "myservice", + EmailDomain: "testdomain.org", + SkipLocalTwoFA: true, + }, + }, + }, + // case 2 + { + args: []string{ + "pam-test", + "--service-name", "myservice", + "--email-domain", "testdomain.org", + "--skip-local-2fa", "false", + "--active", "true", + }, + errMsg: "name must be set", + }, + // case 3 + { + args: []string{ + "pam-test", + "--name", "Pam Service", + "--email-domain", "testdomain.org", + "--skip-local-2fa", "false", + "--active", "true", + }, + errMsg: "service-name must be set", + }, + } + + for n, c := range cases { + // Mock functions. + var createdAuthSource *auth.Source + service := &authService{ + initDB: func(context.Context) error { + return nil + }, + createAuthSource: func(ctx context.Context, authSource *auth.Source) error { + createdAuthSource = authSource + return nil + }, + updateAuthSource: func(ctx context.Context, authSource *auth.Source) error { + assert.FailNow(t, "should not call updateAuthSource", "case: %d", n) + return nil + }, + getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) { + assert.FailNow(t, "should not call getAuthSourceByID", "case: %d", n) + return nil, nil + }, + } + + // Create a copy of command to test + app := cli.Command{} + app.Flags = microcmdAuthAddPAM().Flags + app.Action = service.addPAM + + // Run it + err := app.Run(t.Context(), c.args) + if c.errMsg != "" { + assert.EqualError(t, err, c.errMsg, "case %d: error should match", n) + } else { + require.NoError(t, err, "case %d: should have no errors", n) + assert.Equal(t, c.source, createdAuthSource, "case %d: wrong authSource", n) + } + } +} + +func TestUpdatePAM(t *testing.T) { + // Mock cli functions to do not exit on error + defer test.MockVariableValue(&cli.OsExiter, func(code int) {})() + + // Test cases + cases := []struct { + args []string + id int64 + existingAuthSource *auth.Source + authSource *auth.Source + errMsg string + }{ + // case 0 + { + args: []string{ + "pam-test", + "--id", "23", + "--name", "PAM Service", + "--service-name", "myservice", + }, + id: 23, + existingAuthSource: &auth.Source{ + Type: auth.PAM, + IsActive: true, + Cfg: &pam.Source{}, + }, + authSource: &auth.Source{ + Type: auth.PAM, + Name: "PAM Service", + IsActive: true, + Cfg: &pam.Source{ + ServiceName: "myservice", + }, + }, + }, + // case 1 + { + args: []string{ + "pam-test", + "--id", "1", + }, + authSource: &auth.Source{ + Type: auth.PAM, + Cfg: &pam.Source{}, + }, + }, + // case 2 + { + args: []string{ + "pam-test", + "--id", "1", + "--name", "pam service", + }, + authSource: &auth.Source{ + Type: auth.PAM, + Name: "pam service", + Cfg: &pam.Source{}, + }, + }, + // case 3 + { + args: []string{ + "pam-test", + "--id", "1", + "--active=false", + }, + existingAuthSource: &auth.Source{ + Type: auth.PAM, + IsActive: true, + Cfg: &pam.Source{}, + }, + authSource: &auth.Source{ + Type: auth.PAM, + IsActive: false, + Cfg: &pam.Source{}, + }, + }, + // case 4 + { + args: []string{ + "pam-test", + "--id", "1", + "--service-name", "myservice", + }, + authSource: &auth.Source{ + Type: auth.PAM, + Cfg: &pam.Source{ + ServiceName: "myservice", + }, + }, + }, + // case 5 + { + args: []string{ + "pam-test", + "--id", "1", + "--skip-local-2fa=false", + }, + authSource: &auth.Source{ + Type: auth.PAM, + Cfg: &pam.Source{ + SkipLocalTwoFA: false, + }, + }, + }, + // case 6 + { + args: []string{ + "pam-test", + "--id", "1", + "--email-domain", "testdomain.org", + }, + authSource: &auth.Source{ + Type: auth.PAM, + Cfg: &pam.Source{ + EmailDomain: "testdomain.org", + }, + }, + }, + } + + for n, c := range cases { + // Mock functions. + var updatedAuthSource *auth.Source + service := &authService{ + initDB: func(context.Context) error { + return nil + }, + createAuthSource: func(ctx context.Context, authSource *auth.Source) error { + assert.FailNow(t, "should not call createAuthSource", "case: %d", n) + return nil + }, + updateAuthSource: func(ctx context.Context, authSource *auth.Source) error { + updatedAuthSource = authSource + return nil + }, + getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) { + if c.id != 0 { + assert.Equal(t, c.id, id, "case %d: wrong id", n) + } + if c.existingAuthSource != nil { + return c.existingAuthSource, nil + } + return &auth.Source{ + Type: auth.PAM, + Cfg: &pam.Source{}, + }, nil + }, + } + + // Create a copy of command to test + app := cli.Command{} + app.Flags = microcmdAuthUpdatePAM().Flags + app.Action = service.updatePAM + + // Run it + err := app.Run(t.Context(), c.args) + if c.errMsg != "" { + assert.EqualError(t, err, c.errMsg, "case %d: error should match", n) + } else { + require.NoError(t, err, "case %d: should have no errors", n) + assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n) + } + } +} diff --git a/cmd/doctor.go b/cmd/doctor.go index f557481110..c2ddfef9c5 100644 --- a/cmd/doctor.go +++ b/cmd/doctor.go @@ -15,6 +15,7 @@ import ( "text/tabwriter" "forgejo.org/models/db" + git_model "forgejo.org/models/git" "forgejo.org/models/gitea_migrations" migrate_base "forgejo.org/models/gitea_migrations/base" repo_model "forgejo.org/models/repo" @@ -41,6 +42,7 @@ func cmdDoctor() *cli.Command { cmdRecreateTable(), cmdDoctorConvert(), cmdAvatarStripExif(), + cmdCleanupCommitStatuses(), }, } } @@ -115,6 +117,54 @@ func cmdAvatarStripExif() *cli.Command { } } +func cmdCleanupCommitStatuses() *cli.Command { + return &cli.Command{ + Name: "cleanup-commit-status", + Usage: "Cleanup extra records in commit_status table", + Description: `Forgejo suffered from a bug which caused the creation of more entries in the +"commit_status" table than necessary. This operation removes the redundant +data caused by the bug. Removing this data is almost always safe. +These redundant records can be accessed by users through the API, making it +possible, but unlikely, that removing it could have an impact to +integrating services (API: /repos/{owner}/{repo}/commits/{ref}/statuses). + +It is safe to run while Forgejo is online. + +On very large Forgejo instances, the performance of operation will improve +if the buffer-size option is used with large values. Approximately 130 MB of +memory is required for every 100,000 records in the buffer. + +Bug reference: https://codeberg.org/forgejo/forgejo/issues/10671 +`, + + Before: multipleBefore(noDanglingArgs, PrepareConsoleLoggerLevel(log.INFO)), + Action: runCleanupCommitStatus, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "verbose", + Aliases: []string{"V"}, + Usage: "Show process details", + }, + &cli.BoolFlag{ + Name: "dry-run", + Usage: "Report statistics from the operation but do not modify the database", + }, + &cli.IntFlag{ + Name: "buffer-size", + Usage: "Record count per query while iterating records; larger values are typically faster but use more memory", + // See IterateByKeyset's documentation for performance notes which led to the choice of the default + // buffer size for this operation. + Value: 100000, + }, + &cli.IntFlag{ + Name: "delete-chunk-size", + Usage: "Number of records to delete per DELETE query", + Value: 1000, + }, + }, + } +} + func runRecreateTable(stdCtx context.Context, ctx *cli.Command) error { stdCtx, cancel := installSignals(stdCtx) defer cancel() @@ -322,3 +372,19 @@ func runAvatarStripExif(ctx context.Context, c *cli.Command) error { return nil } + +func runCleanupCommitStatus(ctx context.Context, cli *cli.Command) error { + ctx, cancel := installSignals(ctx) + defer cancel() + + if err := initDB(ctx); err != nil { + return err + } + + bufferSize := cli.Int("buffer-size") + deleteChunkSize := cli.Int("delete-chunk-size") + dryRun := cli.Bool("dry-run") + log.Debug("bufferSize = %d, deleteChunkSize = %d, dryRun = %v", bufferSize, deleteChunkSize, dryRun) + + return git_model.CleanupCommitStatus(ctx, bufferSize, deleteChunkSize, dryRun) +} diff --git a/cmd/hook.go b/cmd/hook.go index d92e84b289..82dcb30866 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -237,7 +237,7 @@ Forgejo or set your environment appropriately.`, "") continue } - fields := bytes.Fields(scanner.Bytes()) + fields := bytes.Split(scanner.Bytes(), []byte(" ")) if len(fields) != 3 { continue } @@ -369,7 +369,7 @@ Forgejo or set your environment appropriately.`, "") continue } - fields := bytes.Fields(scanner.Bytes()) + fields := bytes.Split(scanner.Bytes(), []byte(" ")) if len(fields) != 3 { continue } diff --git a/cmd/hook_test.go b/cmd/hook_test.go index 19e10455cb..a40036ffd5 100644 --- a/cmd/hook_test.go +++ b/cmd/hook_test.go @@ -14,6 +14,9 @@ import ( "testing" "time" + "forgejo.org/modules/git" + "forgejo.org/modules/json" + "forgejo.org/modules/private" "forgejo.org/modules/setting" "forgejo.org/modules/test" @@ -161,3 +164,133 @@ func TestDelayWriter(t *testing.T) { require.Empty(t, out) }) } + +func TestRunHookPrePostReceive(t *testing.T) { + // Setup the environment. + defer test.MockVariableValue(&setting.InternalToken, "Random")() + defer test.MockVariableValue(&setting.InstallLock, true)() + defer test.MockVariableValue(&setting.Git.VerbosePush, true)() + t.Setenv("SSH_ORIGINAL_COMMAND", "true") + + tests := []struct { + name string + inputLine string + oldCommitID string + newCommitID string + refFullName string + }{ + { + name: "base case", + inputLine: "00000000000000000000 00000000000000000001 refs/head/main\n", + oldCommitID: "00000000000000000000", + newCommitID: "00000000000000000001", + refFullName: "refs/head/main", + }, + { + name: "nbsp case", + inputLine: "00000000000000000000 00000000000000000001 refs/head/ma\u00A0in\n", + oldCommitID: "00000000000000000000", + newCommitID: "00000000000000000001", + refFullName: "refs/head/ma\u00A0in", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Setup the Stdin. + f, err := os.OpenFile(t.TempDir()+"/stdin", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666) + require.NoError(t, err) + _, err = f.Write([]byte(tt.inputLine)) + require.NoError(t, err) + _, err = f.Seek(0, 0) + require.NoError(t, err) + defer test.MockVariableValue(os.Stdin, *f)() + + // Setup the server that processes the hooks. + var serverError error + var hookOpts *private.HookOptions + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + if err != nil { + serverError = err + w.WriteHeader(500) + return + } + + err = json.Unmarshal(body, &hookOpts) + if err != nil { + serverError = err + w.WriteHeader(500) + return + } + + w.WriteHeader(200) + + resp := &private.HookPostReceiveResult{} + bytes, err := json.Marshal(resp) + if err != nil { + serverError = err + return + } + + _, err = w.Write(bytes) + if err != nil { + serverError = err + return + } + })) + defer ts.Close() + defer test.MockVariableValue(&setting.LocalURL, ts.URL+"/")() + + t.Run("pre-receive", func(t *testing.T) { + app := cli.Command{} + app.Commands = []*cli.Command{subcmdHookPreReceive()} + + finish := captureOutput(t, os.Stdout) + err = app.Run(t.Context(), []string{"./forgejo", "pre-receive"}) + require.NoError(t, err) + out := finish() + require.Empty(t, out) + + require.NoError(t, serverError) + require.NotNil(t, hookOpts) + + require.Len(t, hookOpts.OldCommitIDs, 1) + assert.Equal(t, tt.oldCommitID, hookOpts.OldCommitIDs[0]) + require.Len(t, hookOpts.NewCommitIDs, 1) + assert.Equal(t, tt.newCommitID, hookOpts.NewCommitIDs[0]) + require.Len(t, hookOpts.RefFullNames, 1) + assert.Equal(t, git.RefName(tt.refFullName), hookOpts.RefFullNames[0]) + }) + + // seek stdin back to beginning + _, err = f.Seek(0, 0) + require.NoError(t, err) + // reset state from prev test + serverError = nil + hookOpts = nil + + t.Run("post-receive", func(t *testing.T) { + app := cli.Command{} + app.Commands = []*cli.Command{subcmdHookPostReceive()} + + finish := captureOutput(t, os.Stdout) + err = app.Run(t.Context(), []string{"./forgejo", "post-receive"}) + require.NoError(t, err) + out := finish() + require.Empty(t, out) + + require.NoError(t, serverError) + require.NotNil(t, hookOpts) + + require.Len(t, hookOpts.OldCommitIDs, 1) + assert.Equal(t, tt.oldCommitID, hookOpts.OldCommitIDs[0]) + require.Len(t, hookOpts.NewCommitIDs, 1) + assert.Equal(t, tt.newCommitID, hookOpts.NewCommitIDs[0]) + require.Len(t, hookOpts.RefFullNames, 1) + assert.Equal(t, git.RefName(tt.refFullName), hookOpts.RefFullNames[0]) + }) + }) + } +} diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index a432a142c3..f45b7731c5 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -362,7 +362,7 @@ RUN_USER = ; git DB_TYPE = sqlite3 ;PATH= ; defaults to data/forgejo.db ;SQLITE_TIMEOUT = ; Query timeout defaults to: 500 -;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode +;SQLITE_JOURNAL_MODE = WAL; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; diff --git a/eslint.config.mjs b/eslint.config.mjs index 61987aef14..df3425d7a0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -528,11 +528,7 @@ export default tseslint.config( 'no-this-before-super': [2], 'no-throw-literal': [2], 'no-undef-init': [2], - - 'no-undef': [2, { - typeof: true, - }], - + 'no-undef': [0], 'no-undefined': [0], 'no-underscore-dangle': [0], 'no-unexpected-multiline': [2], diff --git a/go.mod b/go.mod index 9e1615f9d2..2201d007a6 100644 --- a/go.mod +++ b/go.mod @@ -2,22 +2,22 @@ module forgejo.org go 1.25.0 -toolchain go1.25.5 +toolchain go1.25.9 require ( code.forgejo.org/f3/gof3/v3 v3.11.1 code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 - code.forgejo.org/forgejo/actions-proto v0.5.3 + code.forgejo.org/forgejo/actions-proto v0.6.0 code.forgejo.org/forgejo/go-rpmutils v1.0.0 code.forgejo.org/forgejo/levelqueue v1.0.0 code.forgejo.org/forgejo/reply v1.0.2 - code.forgejo.org/forgejo/runner/v12 v12.2.0 + code.forgejo.org/forgejo/runner/v12 v12.6.4 code.forgejo.org/go-chi/binding v1.0.1 code.forgejo.org/go-chi/cache v1.0.1 code.forgejo.org/go-chi/captcha v1.0.2 code.forgejo.org/go-chi/session v1.0.2 code.gitea.io/sdk/gitea v0.21.0 - code.superseriousbusiness.org/exif-terminator v0.11.0 + code.superseriousbusiness.org/exif-terminator v0.11.1 code.superseriousbusiness.org/go-jpeg-image-structure/v2 v2.3.0 codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 connectrpc.com/connect v1.19.1 @@ -45,7 +45,7 @@ require ( github.com/gliderlabs/ssh v0.3.8 github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77 - github.com/go-chi/chi/v5 v5.2.3 + github.com/go-chi/chi/v5 v5.2.4 github.com/go-chi/cors v1.2.2 github.com/go-co-op/gocron v1.37.0 github.com/go-enry/go-enry/v2 v2.9.2 @@ -58,7 +58,7 @@ require ( github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 github.com/golang-jwt/jwt/v5 v5.3.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 - github.com/google/go-github/v74 v74.0.0 + github.com/google/go-github/v81 v81.0.0 github.com/google/pprof v0.0.0-20251114195745-4902fdda35c8 github.com/google/uuid v1.6.0 github.com/gorilla/feeds v1.2.0 @@ -67,15 +67,15 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/huandu/xstrings v1.5.0 github.com/inbucket/html2text v0.9.0 - github.com/jackc/pgx/v5 v5.7.6 + github.com/jackc/pgx/v5 v5.9.0 github.com/jhillyerd/enmime/v2 v2.2.0 github.com/json-iterator/go v1.1.12 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/klauspost/compress v1.18.2 + github.com/klauspost/compress v1.18.3 github.com/klauspost/cpuid/v2 v2.2.11 github.com/markbates/goth v1.80.0 github.com/mattn/go-isatty v0.0.20 - github.com/mattn/go-sqlite3 v1.14.32 + github.com/mattn/go-sqlite3 v1.14.34 github.com/meilisearch/meilisearch-go v0.34.0 github.com/mholt/archives v0.1.5 github.com/microcosm-cc/bluemonday v1.0.27 @@ -102,13 +102,13 @@ require ( gitlab.com/gitlab-org/api/client-go v0.143.2 go.uber.org/mock v0.6.0 go.yaml.in/yaml/v3 v3.0.4 - golang.org/x/crypto v0.46.0 - golang.org/x/image v0.33.0 - golang.org/x/net v0.47.0 + golang.org/x/crypto v0.49.0 + golang.org/x/image v0.39.0 + golang.org/x/net v0.52.0 golang.org/x/oauth2 v0.34.0 - golang.org/x/sync v0.19.0 - golang.org/x/sys v0.39.0 - golang.org/x/text v0.32.0 + golang.org/x/sync v0.20.0 + golang.org/x/sys v0.42.0 + golang.org/x/text v0.36.0 google.golang.org/protobuf v1.36.11 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/ini.v1 v1.67.0 @@ -120,10 +120,8 @@ require ( require ( cloud.google.com/go/compute/metadata v0.6.0 // indirect code.superseriousbusiness.org/go-png-image-structure/v2 v2.3.0 // indirect - dario.cat/mergo v1.0.2 // indirect - filippo.io/edwards25519 v1.1.0 // indirect + filippo.io/edwards25519 v1.1.1 // indirect git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect github.com/STARRY-S/zip v0.2.3 // indirect github.com/andybalholm/brotli v1.2.0 // indirect @@ -158,8 +156,7 @@ require ( github.com/caddyserver/zerossl v0.1.3 // indirect github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cloudflare/circl v1.6.1 // indirect - github.com/cyphar/filepath-securejoin v0.6.0 // indirect + github.com/cloudflare/circl v1.6.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect @@ -169,7 +166,6 @@ require ( github.com/dsoprea/go-photoshop-info-format v0.0.0-20200609050348-3db9b63b202c // indirect github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect - github.com/emirpasic/gods v1.18.1 // indirect github.com/fatih/color v1.18.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect @@ -178,8 +174,8 @@ require ( github.com/go-errors/errors v1.4.2 // indirect github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.2 // indirect - github.com/go-git/go-git/v5 v5.16.3 // indirect + github.com/go-git/go-billy/v5 v5.8.0 // indirect + github.com/go-git/go-git/v5 v5.18.0 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-openapi/jsonpointer v0.22.3 // indirect github.com/go-openapi/jsonreference v0.21.3 // indirect @@ -195,7 +191,6 @@ require ( github.com/goccy/go-json v0.10.5 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.7.0 // indirect @@ -211,9 +206,8 @@ require ( github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect - github.com/lib/pq v1.10.9 // indirect + github.com/lib/pq v1.11.2 // indirect github.com/libdns/libdns v1.0.0 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/markbates/going v1.0.3 // indirect @@ -239,23 +233,20 @@ require ( github.com/onsi/ginkgo v1.16.5 // indirect github.com/philhofer/fwd v1.2.0 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/rhysd/actionlint v1.7.8 // indirect + github.com/rhysd/actionlint v1.7.10 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rs/xid v1.6.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/skeema/knownhosts v1.3.1 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/tinylib/msgp v1.3.0 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/zeebo/assert v1.3.0 // indirect github.com/zeebo/blake3 v0.2.4 // indirect go.etcd.io/bbolt v1.4.3 // indirect @@ -263,11 +254,11 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go.uber.org/zap/exp v0.3.0 // indirect - go.yaml.in/yaml/v4 v4.0.0-rc.2 // indirect + go.yaml.in/yaml/v4 v4.0.0-rc.3 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/mod v0.31.0 // indirect + golang.org/x/mod v0.34.0 // indirect golang.org/x/time v0.14.0 // indirect - golang.org/x/tools v0.39.0 // indirect + golang.org/x/tools v0.43.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -282,4 +273,4 @@ replace github.com/gliderlabs/ssh => code.forgejo.org/forgejo/ssh v0.0.0-2024121 replace git.sr.ht/~mariusor/go-xsd-duration => code.forgejo.org/forgejo/go-xsd-duration v0.0.0-20220703122237-02e73435a078 -replace xorm.io/xorm v1.3.9 => code.forgejo.org/xorm/xorm v1.3.9-forgejo.4 +replace xorm.io/xorm v1.3.9 => code.forgejo.org/xorm/xorm v1.3.9-forgejo.8 diff --git a/go.sum b/go.sum index 17be63a395..9739506ff1 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ code.forgejo.org/f3/gof3/v3 v3.11.1 h1:c0vE8XvqpbXuSv8gzttn96k5T2FQi0u9bYnux46qS code.forgejo.org/f3/gof3/v3 v3.11.1/go.mod h1:1p2UKrqZiwxKneQF2DKrMnc403YIgR/lfcfvadZtmDs= code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU= code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM= -code.forgejo.org/forgejo/actions-proto v0.5.3 h1:dDProRNB4CDvEl9gfo8jkiVfGdiW7fXAt5TM9Irka28= -code.forgejo.org/forgejo/actions-proto v0.5.3/go.mod h1:33iTdur/jVa/wAQP+BuciRTK9WZcVaxy0BNEnSWWFDM= +code.forgejo.org/forgejo/actions-proto v0.6.0 h1:dw1Dogk9A4V/yrLVkhe9dSZPsqNAIkI1kCXPSqG3tZA= +code.forgejo.org/forgejo/actions-proto v0.6.0/go.mod h1:+444hHBs9/qDh5X/AedaTv0Egj3vd/EXP93vg9zFV2E= code.forgejo.org/forgejo/go-rpmutils v1.0.0 h1:RZGGeKt70p/WaIEL97pyT6uiiEIoN8/aLmS5Z6WmX0M= code.forgejo.org/forgejo/go-rpmutils v1.0.0/go.mod h1:cg+VbgLXfrDPza9T+kBsMb3TVmmzPN4XseT6gDGLSUk= code.forgejo.org/forgejo/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:RArF5AsF9LH4nEoJxqRxcP5r8hhRfWcId84G82YbqzA= @@ -30,8 +30,8 @@ code.forgejo.org/forgejo/levelqueue v1.0.0 h1:9krYpU6BM+j/1Ntj6m+VCAIu0UNnne1/Uf code.forgejo.org/forgejo/levelqueue v1.0.0/go.mod h1:fmG6zhVuqim2rxSFOoasgXO8V2W/k9U31VVYqLIRLhQ= code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ= code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U= -code.forgejo.org/forgejo/runner/v12 v12.2.0 h1:CNRdZqXD32xZOdlQe154c+rIY6VcQ3avEyBqKcAy9SU= -code.forgejo.org/forgejo/runner/v12 v12.2.0/go.mod h1:m6i/RnHQObdagTZUUPR+Nb2Th3VBLOHzjZ6tVw7F0qs= +code.forgejo.org/forgejo/runner/v12 v12.6.4 h1:nhYj2wSj5BVKxcF0bRtMt/A9iGkxHPFJiIui+T/4mrc= +code.forgejo.org/forgejo/runner/v12 v12.6.4/go.mod h1:34ATLtcxtOgjAJiINaJvBoNJiKpL1hGn0kt+gk+zdyk= code.forgejo.org/forgejo/ssh v0.0.0-20241211213324-5fc306ca0616 h1:kEZL84+02jY9RxXM4zHBWZ3Fml0B09cmP1LGkDsCfIA= code.forgejo.org/forgejo/ssh v0.0.0-20241211213324-5fc306ca0616/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= code.forgejo.org/go-chi/binding v1.0.1 h1:coKNI+X1NzRN7X85LlrpvBRqk0TXpJ+ja28vusQWEuY= @@ -42,12 +42,12 @@ code.forgejo.org/go-chi/captcha v1.0.2 h1:vyHDPXkpjDv8bLO9NqtWzZayzstD/WpJ5xwEkA code.forgejo.org/go-chi/captcha v1.0.2/go.mod h1:lxiPLcJ76UCZHoH31/Wbum4GUi2NgjfFZLrJkKv1lLE= code.forgejo.org/go-chi/session v1.0.2 h1:pG+AXre9L9VXJmTaADXkmeEPuRalhmBXyv6tG2Rvjcc= code.forgejo.org/go-chi/session v1.0.2/go.mod h1:HnEGyBny7WPzCiVLP2vzL5ssma+3gCSl/vLpuVNYrqc= -code.forgejo.org/xorm/xorm v1.3.9-forgejo.4 h1:kyJHREXNEIuzpMwQoouTbUldPP6s/UlL3ZAcNlO4C5s= -code.forgejo.org/xorm/xorm v1.3.9-forgejo.4/go.mod h1:5ouTxqMcalQUvlBpQynRpzu/44GwaMpkA1nU+encsDE= +code.forgejo.org/xorm/xorm v1.3.9-forgejo.8 h1:dsSKm2nus0NhHsqYxeuB3Gldk6TtlusD1CBGV6V1SS0= +code.forgejo.org/xorm/xorm v1.3.9-forgejo.8/go.mod h1:A7sFd3BFmRp20h6drSsCXgQRQdF8Vz8HuCSrzFS3m90= code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4= code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA= -code.superseriousbusiness.org/exif-terminator v0.11.0 h1:Hof0MCcsa+1fS17gf86fTTZ8AQnMY9h9kzcc+2C6mVg= -code.superseriousbusiness.org/exif-terminator v0.11.0/go.mod h1:9sutT1axa/kSdlPLlRFjCNKmyo/KNx8eX3XZvWBlAEY= +code.superseriousbusiness.org/exif-terminator v0.11.1 h1:qnujLH4/Yk/CFtFMmtjozbdV6Ry5G3Q/E/mLlWm/gQI= +code.superseriousbusiness.org/exif-terminator v0.11.1/go.mod h1:/Z+3DHSrefCzzN5ePkGjVYKFErRimoeUf694Gz8Pn/Y= code.superseriousbusiness.org/go-jpeg-image-structure/v2 v2.3.0 h1:r9uq8StaSHYKJ8DklR9Xy+E9c40G1Z8yj5TRGi8L6+4= code.superseriousbusiness.org/go-jpeg-image-structure/v2 v2.3.0/go.mod h1:IK1OlR6APjVB3E9tuYGvf0qXMrwP+TrzcHS5rf4wffQ= code.superseriousbusiness.org/go-png-image-structure/v2 v2.3.0 h1:I512jiIeXDC4//2BeSPrRM2ZS4wpBKUaPeTPxakMNGA= @@ -56,11 +56,9 @@ codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtf codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM= connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14= connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= -filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= +filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs= @@ -73,9 +71,6 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo= @@ -102,8 +97,6 @@ github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kk github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 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/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -189,11 +182,9 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= -github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.6.0 h1:BtGB77njd6SVO6VztOHfPxKitJvd/VPT+OFBFMOi1Is= -github.com/cyphar/filepath-securejoin v0.6.0/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -241,8 +232,6 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/editorconfig/editorconfig-core-go/v2 v2.6.4 h1:CHwUbBVVyKWRX9kt5A/OtwhYUJB32DrFp9xzmjR6cac= github.com/editorconfig/editorconfig-core-go/v2 v2.6.4/go.mod h1:JWRVKHdVW+dkv6F8p+xGCa6a+TyMrqsFbFkSs/aQkrQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= 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= @@ -250,8 +239,6 @@ github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTe github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY= github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= @@ -276,8 +263,8 @@ github.com/go-ap/jsonld v0.0.0-20251216162253-e38fa664ea77/go.mod h1:4h93IBxgfnE github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/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.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE= -github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= +github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE= github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= @@ -295,12 +282,10 @@ github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/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.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= -github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.3 h1:Z8BtvxZ09bYm/yYNgPKCzgWtaRqDTgIKRgIRHBfU6Z8= -github.com/go-git/go-git/v5 v5.16.3/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= +github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0= +github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= +github.com/go-git/go-git/v5 v5.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= +github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= 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-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= @@ -369,8 +354,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -401,8 +384,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-github/v74 v74.0.0 h1:yZcddTUn8DPbj11GxnMrNiAnXH14gNs559AsUpNpPgM= -github.com/google/go-github/v74 v74.0.0/go.mod h1:ubn/YdyftV80VPSI26nSJvaEsTOnsjrxG3o9kJhcyak= +github.com/google/go-github/v81 v81.0.0 h1:hTLugQRxSLD1Yei18fk4A5eYjOGLUBKAl/VCqOfFkZc= +github.com/google/go-github/v81 v81.0.0/go.mod h1:upyjaybucIbBIuxgJS7YLOZGziyvvJ92WX6WEBNE3sM= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU= @@ -462,8 +445,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= -github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/pgx/v5 v5.9.0 h1:T/dI+2TvmI2H8s/KH1/lXIbz1CUFk3gn5oTjr0/mBsE= +github.com/jackc/pgx/v5 v5.9.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -492,12 +475,10 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= -github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= +github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= 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.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU= @@ -516,8 +497,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= +github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= github.com/libdns/libdns v1.0.0 h1:IvYaz07JNz6jUQ4h/fv2R4sVnRnm77J/aOuC9B+TQTA= github.com/libdns/libdns v1.0.0/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= @@ -535,8 +516,8 @@ github.com/mattn/go-runewidth v0.0.17 h1:78v8ZlW0bP43XfmAfPsdXcoNCelfMHsDmd/pkEN github.com/mattn/go-runewidth v0.0.17/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= -github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk= +github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/meilisearch/meilisearch-go v0.34.0 h1:P+Ohdx4/PCxXaoI5wNi0LMwPkuiNrF/kGIzBrKYS4tw= github.com/meilisearch/meilisearch-go v0.34.0/go.mod h1:cUVJZ2zMqTvvwIMEEAdsWH+zrHsrLpAw6gm8Lt1MXK0= github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= @@ -572,8 +553,8 @@ github.com/msteinert/pam/v2 v2.1.0 h1:er5F9TKV5nGFuTt12ubtqPHEUdeBwReP7vd3wovidG github.com/msteinert/pam/v2 v2.1.0/go.mod h1:KT28NNIcDFf3PcBmNI2mIGO4zZJ+9RSs/At2PB3IDVc= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/niklasfasching/go-org v1.9.1 h1:/3s4uTPOF06pImGa2Yvlp24yKXZoTYM+nsIlMzfpg/0= github.com/niklasfasching/go-org v1.9.1/go.mod h1:ZAGFFkWvUQcpazmi/8nHqwvARpr1xpb+Es67oUGX/48= github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A= @@ -608,8 +589,6 @@ github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -631,8 +610,8 @@ github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4Vi github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rhysd/actionlint v1.7.8 h1:3d+N9ourgAxVYG4z2IFxFIk/YiT6V+VnKASfXGwT60E= -github.com/rhysd/actionlint v1.7.8/go.mod h1:3kiS6egcbXG+vQsJIhFxTz+UKaF1JprsE0SKrpCZKvU= +github.com/rhysd/actionlint v1.7.10 h1:FL3XIEs72G4/++168vlv5FKOWMSWvWIQw1kBCadyOcM= +github.com/rhysd/actionlint v1.7.10/go.mod h1:ZHX/hrmknlsJN73InPTKsKdXpAv9wVdrJy8h8HAwFHg= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -651,11 +630,8 @@ github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCw github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -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.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= -github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik= github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= @@ -667,7 +643,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -692,8 +667,6 @@ github.com/valyala/fastjson v1.6.7 h1:ZE4tRy0CIkh+qDc5McjatheGX2czdn8slQjomexVpB github.com/valyala/fastjson v1.6.7/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= 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/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js= @@ -734,8 +707,8 @@ go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U= go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s= -go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= +go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go= +go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -745,13 +718,12 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= 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= @@ -760,12 +732,12 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= +golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.33.0 h1:LXRZRnv1+zGd5XBUVRFmYEphyyKJjQjCRiOuAP3sZfQ= -golang.org/x/image v0.33.0/go.mod h1:DD3OsTYT9chzuzTQt+zMcOlBHgfoKQb1gry8p76Y1sc= +golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= +golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -787,8 +759,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= -golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= 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= @@ -810,7 +782,6 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -820,8 +791,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= +golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= 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= @@ -842,8 +813,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -856,7 +827,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -865,13 +835,10 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -882,8 +849,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= 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= @@ -893,8 +860,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= +golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= 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= @@ -908,8 +875,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= @@ -943,8 +910,8 @@ 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.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1026,14 +993,14 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A= -modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I= +modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= +modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/sqlite v1.39.1 h1:H+/wGFzuSCIEVCvXYVHX5RQglwhMOvtHSv+VtidL2r4= -modernc.org/sqlite v1.39.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE= +modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU= +modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8= mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/models/actions/run.go b/models/actions/run.go index 8194c07940..08fd445091 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -455,6 +455,10 @@ func GetRunByIndex(ctx context.Context, repoID, index int64) (*ActionRun, error) return run, nil } +// Error returned when ActionRun's optimistic concurrency control has indicated that the record has been updated in the +// database by another session since it was loaded in-memory in this session. +var ErrActionRunOutOfDate = errors.New("run has changed") + // UpdateRun updates a run. // It requires the inputted run has Version set. // It will return error if the version is not matched (it means the run has been changed after loaded). @@ -471,8 +475,9 @@ func UpdateRunWithoutNotification(ctx context.Context, run *ActionRun, cols ...s return err } if affected == 0 { - return errors.New("run has changed") - // It's impossible that the run is not found, since Gitea never deletes runs. + // UPDATE has no conditions on it, and we never delete runs, so the only possible cause of this is + // `xorm:"version"` tagged field indicated that the version has changed since the record was loaded. + return ErrActionRunOutOfDate } if run.Status != 0 || slices.Contains(cols, "status") { @@ -495,4 +500,35 @@ func UpdateRunWithoutNotification(ctx context.Context, run *ActionRun, cols ...s return nil } +// Compute the Status, Started, and Stopped fields of an ActionRun based upon the current job state within the run. +// Returned is the [ActionRun] with modifications if necessary, a slice of column names that have been updated, or an +// error if the calculation failed. The caller is responsible for then invoking [actions_service.UpdateRun] for an +// update with notifications, or [actions_model.UpdateRunWithoutNotification] if notifications are already handled. +func ComputeRunStatus(ctx context.Context, runID int64) (run *ActionRun, columns []string, err error) { + run, err = GetRunByID(ctx, runID) + if err != nil { + return nil, nil, err + } + jobs, err := GetRunJobsByRunID(ctx, runID) + if err != nil { + return nil, nil, err + } + + newStatus := AggregateJobStatus(jobs) + if run.Status != newStatus { + run.Status = newStatus + columns = append(columns, "status") + } + if run.Started.IsZero() && run.Status.IsRunning() { + run.Started = timeutil.TimeStampNow() + columns = append(columns, "started") + } + if run.Stopped.IsZero() && run.Status.IsDone() { + run.Stopped = timeutil.TimeStampNow() + columns = append(columns, "stopped") + } + + return run, columns, nil +} + type ActionRunIndex db.ResourceIndex diff --git a/models/actions/run_job.go b/models/actions/run_job.go index 8096bfb6b5..ed1cefbaa5 100644 --- a/models/actions/run_job.go +++ b/models/actions/run_job.go @@ -137,6 +137,22 @@ func GetRunJobsByRunID(ctx context.Context, runID int64) ([]*ActionRunJob, error return jobs, nil } +// Check if the ActionRun has any jobs other than those included in the jobs parameter. +func RunHasOtherJobs(ctx context.Context, runID int64, jobs []*ActionRunJob) (bool, error) { + jobIDs := make([]int64, len(jobs)) + for i, job := range jobs { + jobIDs[i] = job.ID + } + otherJobs, err := db.GetEngine(ctx). + Where("run_id = ?", runID). + Where(builder.NotIn("id", jobIDs)). + Count(&ActionRunJob{}) + if err != nil { + return false, err + } + return otherJobs > 0, nil +} + // All calls to UpdateRunJobWithoutNotification that change run.Status for any run from a not done status to a done status must call the ActionRunNowDone notification channel. // Use the wrapper function UpdateRunJob instead. func UpdateRunJobWithoutNotification(ctx context.Context, job *ActionRunJob, cond builder.Cond, cols ...string) (int64, error) { @@ -174,34 +190,18 @@ func UpdateRunJobWithoutNotification(ctx context.Context, job *ActionRunJob, con } } - { - // Other goroutines may aggregate the status of the run and update it too. - // So we need load the run and its jobs before updating the run. - run, err := GetRunByID(ctx, job.RunID) - if err != nil { - return 0, err - } - jobs, err := GetRunJobsByRunID(ctx, job.RunID) - if err != nil { - return 0, err - } - run.Status = AggregateJobStatus(jobs) - if run.Started.IsZero() && run.Status.IsRunning() { - run.Started = timeutil.TimeStampNow() - } - if run.Stopped.IsZero() && run.Status.IsDone() { - run.Stopped = timeutil.TimeStampNow() - } - // As the caller has to ensure the ActionRunNowDone notification is sent we can ignore doing so here. - if err := UpdateRunWithoutNotification(ctx, run, "status", "started", "stopped"); err != nil { - return 0, fmt.Errorf("update run %d: %w", run.ID, err) - } + run, columns, err := ComputeRunStatus(ctx, job.RunID) + if err != nil { + return 0, fmt.Errorf("compute run status: %w", err) + } + if err := UpdateRunWithoutNotification(ctx, run, columns...); err != nil { + return 0, fmt.Errorf("update run %d: %w", run.ID, err) } return affected, nil } -func AggregateJobStatus(jobs []*ActionRunJob) Status { +var AggregateJobStatus = func(jobs []*ActionRunJob) Status { allSuccessOrSkipped := len(jobs) != 0 allSkipped := len(jobs) != 0 var hasFailure, hasCancelled, hasWaiting, hasRunning, hasBlocked bool diff --git a/models/actions/run_job_list.go b/models/actions/run_job_list.go index afc754f26a..f4cc4bfb45 100644 --- a/models/actions/run_job_list.go +++ b/models/actions/run_job_list.go @@ -8,6 +8,7 @@ import ( "forgejo.org/models/db" "forgejo.org/modules/container" + "forgejo.org/modules/optional" "forgejo.org/modules/timeutil" "xorm.io/builder" @@ -48,14 +49,15 @@ func (jobs ActionJobList) LoadAttributes(ctx context.Context, withRepo bool) err type FindRunJobOptions struct { db.ListOptions - RunID int64 - RepoID int64 - OwnerID int64 - CommitSHA string - Statuses []Status - UpdatedBefore timeutil.TimeStamp - Events []string // []webhook_module.HookEventType - RunNumber int64 + RunID int64 + RepoID int64 + OwnerID int64 + CommitSHA string + Statuses []Status + UpdatedBefore timeutil.TimeStamp + Events []string // []webhook_module.HookEventType + RunNumber int64 + RunNeedsApproval optional.Option[bool] } func (opts FindRunJobOptions) ToConds() builder.Cond { @@ -84,5 +86,12 @@ func (opts FindRunJobOptions) ToConds() builder.Cond { if opts.RunNumber > 0 { cond = cond.And(builder.Eq{"`index`": opts.RunNumber}) } + if opts.RunNeedsApproval.Has() { + cond = cond.And(builder.Exists(builder.Select("id").From("action_run", "outer_run"). + Where(builder.Eq{ + "outer_run.need_approval": opts.RunNeedsApproval.Value(), + "outer_run.id": builder.Expr("run_id"), + }))) + } return cond } diff --git a/models/actions/run_job_test.go b/models/actions/run_job_test.go index 9cba48705b..c122b1ff55 100644 --- a/models/actions/run_job_test.go +++ b/models/actions/run_job_test.go @@ -159,3 +159,23 @@ func TestActionRunJob_IsIncompleteRunsOn(t *testing.T) { }) } } + +func TestRunHasOtherJobs(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + jobs, err := GetRunJobsByRunID(t.Context(), 791) + require.NoError(t, err) + assert.Len(t, jobs, 1) + + has, err := RunHasOtherJobs(t.Context(), 791, nil) + require.NoError(t, err) + assert.True(t, has) + + has, err = RunHasOtherJobs(t.Context(), 791, []*ActionRunJob{}) + require.NoError(t, err) + assert.True(t, has) + + has, err = RunHasOtherJobs(t.Context(), 791, jobs) + require.NoError(t, err) + assert.False(t, has) +} diff --git a/models/actions/run_list.go b/models/actions/run_list.go index 174d2aa70c..92be510569 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -5,7 +5,6 @@ package actions import ( "context" - "strings" "forgejo.org/models/db" repo_model "forgejo.org/models/repo" @@ -65,15 +64,14 @@ func (runs RunList) LoadRepos(ctx context.Context) error { type FindRunOptions struct { db.ListOptions - RepoID int64 - OwnerID int64 - WorkflowID string - Ref string // the commit/tag/… that caused this workflow - TriggerUserID int64 - TriggerEvent webhook_module.HookEventType - Approved bool // not util.OptionalBool, it works only when it's true - Status []Status - ConcurrencyGroup string + RepoID int64 + OwnerID int64 + WorkflowID string + Ref string // the commit/tag/… that caused this workflow + TriggerUserID int64 + TriggerEvent webhook_module.HookEventType + Approved bool // not util.OptionalBool, it works only when it's true + Status []Status } func (opts FindRunOptions) ToConds() builder.Cond { @@ -102,9 +100,6 @@ func (opts FindRunOptions) ToConds() builder.Cond { if opts.TriggerEvent != "" { cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent}) } - if opts.ConcurrencyGroup != "" { - cond = cond.And(builder.Eq{"concurrency_group": strings.ToLower(opts.ConcurrencyGroup)}) - } return cond } diff --git a/models/actions/run_test.go b/models/actions/run_test.go index 3a169dd56a..064f3fbcea 100644 --- a/models/actions/run_test.go +++ b/models/actions/run_test.go @@ -272,3 +272,122 @@ jobs: // Expect job with an incomplete runs-on to be StatusBlocked: assert.Equal(t, StatusBlocked, job.Status) } + +func TestComputeRunStatus(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + t.Run("no changes", func(t *testing.T) { + run, columns, err := ComputeRunStatus(t.Context(), 791) + require.NoError(t, err) + assert.Equal(t, StatusSuccess, run.Status) + assert.NotContains(t, columns, "status") + assert.EqualValues(t, 1683636528, run.Started) + assert.NotContains(t, columns, "started") + assert.EqualValues(t, 1683636626, run.Stopped) + assert.NotContains(t, columns, "stopped") + }) + + t.Run("change status", func(t *testing.T) { + job := unittest.AssertExistsAndLoadBean(t, &ActionRunJob{ID: 192}) + job.Status = StatusFailure + affected, err := db.GetEngine(t.Context()).Cols("status").ID(job.ID).Update(job) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + run, columns, err := ComputeRunStatus(t.Context(), 791) + require.NoError(t, err) + assert.Equal(t, StatusFailure, run.Status) + assert.Contains(t, columns, "status") + assert.NotContains(t, columns, "started") + assert.NotContains(t, columns, "stopped") + }) + + t.Run("won't change started if not running", func(t *testing.T) { + job := unittest.AssertExistsAndLoadBean(t, &ActionRunJob{ID: 192}) + job.Status = StatusBlocked + affected, err := db.GetEngine(t.Context()).Cols("status").ID(job.ID).Update(job) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + preRun := unittest.AssertExistsAndLoadBean(t, &ActionRun{ID: 791}) + preRun.Started = 0 + affected, err = db.GetEngine(t.Context()).Cols("started").ID(preRun.ID).Update(preRun) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + run, columns, err := ComputeRunStatus(t.Context(), 791) + require.NoError(t, err) + assert.Equal(t, StatusBlocked, run.Status) + assert.EqualValues(t, 0, run.Started) + assert.Contains(t, columns, "status") + assert.NotContains(t, columns, "started") + assert.NotContains(t, columns, "stopped") + }) + + t.Run("change started", func(t *testing.T) { + // Need the job to be "Running" for started to appear to change + job := unittest.AssertExistsAndLoadBean(t, &ActionRunJob{ID: 192}) + job.Status = StatusRunning + affected, err := db.GetEngine(t.Context()).Cols("status").ID(job.ID).Update(job) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + preRun := unittest.AssertExistsAndLoadBean(t, &ActionRun{ID: 791}) + preRun.Started = 0 + affected, err = db.GetEngine(t.Context()).Cols("started").ID(preRun.ID).Update(preRun) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + run, columns, err := ComputeRunStatus(t.Context(), 791) + require.NoError(t, err) + assert.Equal(t, StatusRunning, run.Status) + assert.NotEqualValues(t, 0, run.Started) + assert.Contains(t, columns, "status") + assert.Contains(t, columns, "started") + assert.NotContains(t, columns, "stopped") + }) + + t.Run("won't change stopped if not done", func(t *testing.T) { + job := unittest.AssertExistsAndLoadBean(t, &ActionRunJob{ID: 192}) + job.Status = StatusRunning + affected, err := db.GetEngine(t.Context()).Cols("status").ID(job.ID).Update(job) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + preRun := unittest.AssertExistsAndLoadBean(t, &ActionRun{ID: 791}) + preRun.Stopped = 0 + affected, err = db.GetEngine(t.Context()).Cols("stopped").ID(preRun.ID).Update(preRun) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + run, columns, err := ComputeRunStatus(t.Context(), 791) + require.NoError(t, err) + assert.Equal(t, StatusRunning, run.Status) + assert.EqualValues(t, 0, run.Stopped) + assert.Contains(t, columns, "status") + assert.NotContains(t, columns, "stopped") + }) + + t.Run("change stopped", func(t *testing.T) { + // Need the job to be some version of Done for stopped to appear to change + job := unittest.AssertExistsAndLoadBean(t, &ActionRunJob{ID: 192}) + job.Status = StatusSuccess + affected, err := db.GetEngine(t.Context()).Cols("status").ID(job.ID).Update(job) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + preRun := unittest.AssertExistsAndLoadBean(t, &ActionRun{ID: 791}) + preRun.Stopped = 0 + affected, err = db.GetEngine(t.Context()).Cols("stopped").ID(preRun.ID).Update(preRun) + require.NoError(t, err) + require.EqualValues(t, 1, affected) + + run, columns, err := ComputeRunStatus(t.Context(), 791) + require.NoError(t, err) + assert.Equal(t, StatusSuccess, run.Status) + assert.NotEqualValues(t, 0, run.Stopped) + assert.NotContains(t, columns, "status") + assert.NotContains(t, columns, "started") + assert.Contains(t, columns, "stopped") + }) +} diff --git a/models/activities/main_test.go b/models/activities/main_test.go index a5245ab1d3..403cf10c0f 100644 --- a/models/activities/main_test.go +++ b/models/activities/main_test.go @@ -7,10 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/forgefed" ) func TestMain(m *testing.M) { diff --git a/models/asymkey/gpg_key.go b/models/asymkey/gpg_key.go index 64866da076..cae717011e 100644 --- a/models/asymkey/gpg_key.go +++ b/models/asymkey/gpg_key.go @@ -111,7 +111,13 @@ func GPGKeyToEntity(ctx context.Context, k *GPGKey) (*openpgp.Entity, error) { if err != nil { return nil, err } - return keys[0], err + + for _, key := range keys { + if key.PrimaryKey.KeyIdString() == k.KeyID { + return key, nil + } + } + return nil, fmt.Errorf("key with %s id not found", k.KeyID) } // parseSubGPGKey parse a sub Key diff --git a/models/auth/main_test.go b/models/auth/main_test.go index b30db24483..5b8ca00831 100644 --- a/models/auth/main_test.go +++ b/models/auth/main_test.go @@ -8,12 +8,7 @@ import ( "forgejo.org/models/unittest" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/auth" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/perm/access" + _ "forgejo.org/modules/testimport" ) func TestMain(m *testing.M) { diff --git a/models/avatars/main_test.go b/models/avatars/main_test.go index bdc66954b1..f8c90a09e6 100644 --- a/models/avatars/main_test.go +++ b/models/avatars/main_test.go @@ -7,10 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/perm/access" ) func TestMain(m *testing.M) { diff --git a/models/db/context.go b/models/db/context.go index 9be158ccca..89b6c96555 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -6,6 +6,8 @@ package db import ( "context" "database/sql" + "fmt" + "slices" "xorm.io/builder" "xorm.io/xorm" @@ -268,6 +270,48 @@ func GetByID[T any](ctx context.Context, id int64) (object *T, exist bool, err e return &bean, true, nil } +// Retrieves multiple objects with database queries similar to an xorm `.In(idField, idList)`. idField must be a unique +// field on the database table, as a map[id]obj is returned and the usage of a non-unique field would result in objects +// being overwritten in the map. +// +// The length of the IN list is constrained to DefaultMaxInSize for each database query, resulting in multiple database +// queries if the length of the idList exceeds that setting; this constraint prevents exceeding bind parameter +// limitations or query length limitations in the database engine. +func GetByIDs[Bean any, Id comparable](ctx context.Context, idField string, idList []Id, bean *Bean) (map[Id]*Bean, error) { + retval := make(map[Id]*Bean, len(idList)) + if len(idList) == 0 { + return retval, nil + } + + table, err := TableInfo(bean) + if err != nil { + return nil, fmt.Errorf("unable to fetch table info for bean %v: %w", bean, err) + } + + var structFieldName string + for _, c := range table.Columns() { + if c.Name == idField { + structFieldName = c.FieldName + break + } + } + if structFieldName == "" { + return nil, fmt.Errorf("unable to identify struct field for id field %s", idField) + } + + for idChunk := range slices.Chunk(idList, DefaultMaxInSize) { + beans := make([]*Bean, 0, len(idChunk)) + if err := GetEngine(ctx).In(idField, idChunk).Find(&beans); err != nil { + return nil, err + } + for _, bean := range beans { + retval[extractFieldValue(bean, structFieldName).(Id)] = bean + } + } + + return retval, nil +} + func Exist[T any](ctx context.Context, cond builder.Cond) (bool, error) { if !cond.IsValid() { panic("cond is invalid in db.Exist(ctx, cond). This should not be possible.") diff --git a/models/db/iterate.go b/models/db/iterate.go index 5e30b5e8bc..d2315cb12c 100644 --- a/models/db/iterate.go +++ b/models/db/iterate.go @@ -5,8 +5,10 @@ package db import ( "context" + "errors" "fmt" "reflect" + "strings" "forgejo.org/modules/setting" @@ -84,3 +86,123 @@ func extractFieldValue(bean any, fieldName string) any { field := v.FieldByName(fieldName) return field.Interface() } + +// IterateByKeyset iterates all the records on a database (matching the provided condition) in the order of specified +// order fields, and invokes the provided handler function for each record. It is safe to UPDATE or DELETE the record in +// the handler function, as long as the order fields are not mutated on the record (which could cause records to be +// missed or iterated multiple times). +// +// Assuming order fields a, b, and c, then database queries will be performed as "SELECT * FROM table WHERE (a, b, c) > +// (last_a, last_b, last_c) ORDER BY a, b, c LIMIT buffer_size" repeatedly until the query returns no records (except +// the first query will have no WHERE clause). +// +// Critical requirements for proper usage: +// +// - the order fields encompass at least one UNIQUE or PRIMARY KEY constraint of the table to ensure that records are +// not duplicated -- for example, if the table has a unique index covering `(repo_id, index)`, then it would be safe to +// use this function as long as both fields (in either order) are provided as order fields. +// +// - none of the order fields may have NULL values in them, as the `=` and `>` comparisons being performed by the +// iterative queries will not operate on these records consistently as they do with other values. +// +// This implementation could be a much simpler streaming scan of the query results, except that doesn't permit making +// any additional database queries or data modifications in the target function -- SQLite cannot write while holding a +// read lock. Buffering pages of data in-memory avoids that issue. +// +// Performance: +// +// - High performance will result from an alignment of an index on the table with the order fields, in the same field +// order, even if additional ordering fields could be provided after the index fields. In the absence of this index +// alignment, it is reasonable to expect that every extra page of data accessed will require a query that will perform +// an index scan (if available) or sequential scan of the target table. In testing on the `commit_status` table with +// 455k records, a fully index-supported ordering allowed each query page to execute in 0.18ms, as opposed to 80ms +// per-query without matching supporting index. +// +// - In the absence of a matching index, slower per-query performance can be compensated with a larger `batchSize` +// parameter, which controls how many records to fetch at once and therefore reduces the number of queries required. +// This requires more memory. Similar `commit_status` table testing showed these stats for iteration time and memory +// usage for different buffer sizes; specifics will vary depending on the target table: +// - buffer size = 1,000,000 - iterates in 2.8 seconds, consumes 363 MB of RAM +// - buffer size = 100,000 - iterates in 3.5 seconds, consume 130 MB of RAM +// - buffer size = 10,000 - iterates in 7.1 seconds, consumes 59 MB of RAM +// - buffer size = 1,000 - iterates in 33.9 seconds, consumes 42 MB of RAM +func IterateByKeyset[Bean any](ctx context.Context, cond builder.Cond, orderFields []string, batchSize int, f func(ctx context.Context, bean *Bean) error) error { + var dummy Bean + + if len(orderFields) == 0 { + return errors.New("orderFields must be provided") + } + + table, err := TableInfo(&dummy) + if err != nil { + return fmt.Errorf("unable to fetch table info for bean %v: %w", dummy, err) + } + goFieldNames := make([]string, len(orderFields)) + for i, f := range orderFields { + goFieldNames[i] = table.GetColumn(f).FieldName + } + sqlFieldNames := make([]string, len(orderFields)) + for i, f := range orderFields { + // Support field names like "index" which need quoting in builder.Cond & OrderBy + sqlFieldNames[i] = x.Dialect().Quoter().Quote(f) + } + + var lastKey []any + + // For the order fields, generate clauses (a, b, c) and (?, ?, ?) which will be used in the WHERE clause when + // reading additional pages of data. + rowValue := strings.Builder{} + rowParameterValue := strings.Builder{} + rowValue.WriteString("(") + rowParameterValue.WriteString("(") + for i, f := range sqlFieldNames { + rowValue.WriteString(f) + rowParameterValue.WriteString("?") + if i != len(sqlFieldNames)-1 { + rowValue.WriteString(", ") + rowParameterValue.WriteString(", ") + } + } + rowValue.WriteString(")") + rowParameterValue.WriteString(")") + + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + beans := make([]*Bean, 0, batchSize) + + sess := GetEngine(ctx) + for _, f := range sqlFieldNames { + sess = sess.OrderBy(f) + } + if cond != nil { + sess = sess.Where(cond) + } + if lastKey != nil { + sess = sess.Where( + builder.Expr(fmt.Sprintf("%s > %s", rowValue.String(), rowParameterValue.String()), lastKey...)) + } + + if err := sess.Limit(batchSize).Find(&beans); err != nil { + return err + } + if len(beans) == 0 { + return nil + } + + for _, bean := range beans { + if err := f(ctx, bean); err != nil { + return err + } + } + + lastBean := beans[len(beans)-1] + lastKey = make([]any, len(goFieldNames)) + for i := range goFieldNames { + lastKey[i] = extractFieldValue(lastBean, goFieldNames[i]) + } + } + } +} diff --git a/models/db/iterate_test.go b/models/db/iterate_test.go index 405db84866..d60db3da11 100644 --- a/models/db/iterate_test.go +++ b/models/db/iterate_test.go @@ -10,6 +10,7 @@ import ( "testing" "forgejo.org/models/db" + git_model "forgejo.org/models/git" repo_model "forgejo.org/models/repo" "forgejo.org/models/unittest" "forgejo.org/modules/setting" @@ -21,7 +22,6 @@ import ( ) func TestIterate(t *testing.T) { - db.SetLogSQL(t.Context(), true) defer test.MockVariableValue(&setting.Database.IterateBufferSize, 50)() t.Run("No Modifications", func(t *testing.T) { @@ -115,3 +115,31 @@ func TestIterate(t *testing.T) { assert.Empty(t, remainingRepoIDs) }) } + +func TestIterateMultipleFields(t *testing.T) { + for _, bufferSize := range []int{1, 2, 3, 10} { // 8 records in fixture + t.Run(fmt.Sprintf("No Modifications bufferSize=%d", bufferSize), func(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + // Fetch all the commit status IDs... + var remainingIDs []int64 + err := db.GetEngine(t.Context()).Table(&git_model.CommitStatus{}).Cols("id").Find(&remainingIDs) + require.NoError(t, err) + require.NotEmpty(t, remainingIDs) + + // Ensure that every repo unit ID is found when doing iterate: + err = db.IterateByKeyset(t.Context(), + nil, + []string{"repo_id", "sha", "context", "index", "id"}, + bufferSize, + func(ctx context.Context, commit_status *git_model.CommitStatus) error { + remainingIDs = slices.DeleteFunc(remainingIDs, func(n int64) bool { + return commit_status.ID == n + }) + return nil + }) + require.NoError(t, err) + assert.Empty(t, remainingIDs) + }) + } +} diff --git a/models/db/main_test.go b/models/db/main_test.go index 4b06923950..77773b5d34 100644 --- a/models/db/main_test.go +++ b/models/db/main_test.go @@ -7,9 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/repo" ) func TestMain(m *testing.M) { diff --git a/models/fixtures/action_run.yml b/models/fixtures/action_run.yml index 8fa04b0066..41559ef788 100644 --- a/models/fixtures/action_run.yml +++ b/models/fixtures/action_run.yml @@ -533,3 +533,43 @@ updated: 1683636626 need_approval: false approved_by: 0 + +- + id: 895 + title: "job output" + repo_id: 4 + owner_id: 1 + workflow_id: "test.yaml" + index: 191 + trigger_user_id: 1 + ref: "refs/heads/master" + commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" + event: "push" + is_fork_pull_request: false + status: 2 + started: 1683636528 + stopped: 1683636626 + created: 1683636108 + updated: 1683636626 + need_approval: false + approved_by: 0 + +- + id: 896 + title: "job output" + repo_id: 4 + owner_id: 1 + workflow_id: "test.yaml" + index: 192 + trigger_user_id: 1 + ref: "refs/heads/master" + commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" + event: "push" + is_fork_pull_request: false + status: 2 + started: 1683636528 + stopped: 1683636626 + created: 1683636108 + updated: 1683636626 + need_approval: false + approved_by: 0 diff --git a/models/fixtures/action_run_job.yml b/models/fixtures/action_run_job.yml index bb812c1570..2d8ea9ff6f 100644 --- a/models/fixtures/action_run_job.yml +++ b/models/fixtures/action_run_job.yml @@ -69,6 +69,66 @@ status: 5 started: 1683636528 stopped: 1683636626 +- + id: 197 + run_id: 895 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + name: job1 (1) + attempt: 0 + job_id: job1 + task_id: 54 + status: 2 # failure + runs_on: '["postmarketOS"]' + started: 1683636528 + stopped: 1683636626 +- + id: 198 + run_id: 895 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + name: job1 (2) + attempt: 0 + job_id: job1 + task_id: 55 + status: 6 # running + runs_on: '["postmarketOS"]' + started: 1683636528 + stopped: 1683636626 +- + id: 199 + run_id: 896 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + name: job1 (1) + attempt: 0 + job_id: job1 + task_id: 56 + status: 2 # failure + runs_on: '["postmarketOS"]' + started: 1683636528 + stopped: 1683636626 +- + id: 200 + run_id: 896 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + name: job1 (2) + attempt: 0 + job_id: job1 + task_id: 57 + status: 1 # success + runs_on: '["postmarketOS"]' + started: 1683636528 + stopped: 1683636626 - id: 292 run_id: 891 diff --git a/models/fixtures/action_task.yml b/models/fixtures/action_task.yml index 956bc736f9..b931ca0aa8 100644 --- a/models/fixtures/action_task.yml +++ b/models/fixtures/action_task.yml @@ -157,3 +157,83 @@ log_length: 707 log_size: 90179 log_expired: false +- + id: 54 + job_id: 197 + attempt: 0 + runner_id: 1 + status: 2 # failure + started: 1683636528 + stopped: 1683636626 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + token_hash: b8d3962425466b6709b9ac51446f93260c54afe8e7b6d3686e34f991fb8a8953822b0deed86fe41a103f34bc48dbc4784225 + token_salt: ffffffffff + token_last_eight: ffffffff + log_filename: artifact-test2/2f/47.log + log_in_storage: true + log_length: 707 + log_size: 90179 + log_expired: false +- + id: 55 + job_id: 198 + attempt: 0 + runner_id: 1 + status: 6 # running + started: 1683636528 + stopped: 1683636626 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + token_hash: b8d3962425466b6709b9ac51446f93260c54afe8e7b6d3686e34f991fb8a8953822b0deed86fe41a103f34bc48dbc4784226 + token_salt: ffffffffff + token_last_eight: ffffffff + log_filename: artifact-test2/2f/47.log + log_in_storage: true + log_length: 707 + log_size: 90179 + log_expired: false +- + id: 56 + job_id: 199 + attempt: 0 + runner_id: 1 + status: 2 # failure + started: 1683636528 + stopped: 1683636626 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + token_hash: b8d3962425466b6709b9ac51446f93260c54afe8e7b6d3686e34f991fb8a8953822b0deed86fe41a103f34bc48dbc4784227 + token_salt: ffffffffff + token_last_eight: ffffffff + log_filename: artifact-test2/2f/47.log + log_in_storage: true + log_length: 707 + log_size: 90179 + log_expired: false +- + id: 57 + job_id: 200 + attempt: 0 + runner_id: 1 + status: 1 # success + started: 1683636528 + stopped: 1683636626 + repo_id: 4 + owner_id: 1 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: false + token_hash: b8d3962425466b6709b9ac51446f93260c54afe8e7b6d3686e34f991fb8a8953822b0deed86fe41a103f34bc48dbc4784228 + token_salt: ffffffffff + token_last_eight: ffffffff + log_filename: artifact-test2/2f/47.log + log_in_storage: true + log_length: 707 + log_size: 90179 + log_expired: false diff --git a/models/fixtures/project.yml b/models/fixtures/project.yml index 44d87bce04..54a3061859 100644 --- a/models/fixtures/project.yml +++ b/models/fixtures/project.yml @@ -42,7 +42,7 @@ is_closed: false creator_id: 2 board_type: 1 - type: 2 + type: 1 created_unix: 1688973000 updated_unix: 1688973000 @@ -54,7 +54,7 @@ is_closed: false creator_id: 2 board_type: 1 - type: 2 + type: 1 created_unix: 1688973000 updated_unix: 1688973000 @@ -66,6 +66,18 @@ is_closed: false creator_id: 2 board_type: 1 - type: 2 + type: 1 + created_unix: 1688973000 + updated_unix: 1688973000 + +- + id: 7 + title: project on org3 + owner_id: 3 + repo_id: 0 + is_closed: false + creator_id: 2 + board_type: 1 + type: 1 created_unix: 1688973000 updated_unix: 1688973000 diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml index fa7607abcd..4e957f30f3 100644 --- a/models/fixtures/user.yml +++ b/models/fixtures/user.yml @@ -46,6 +46,7 @@ email: user2@example.com keep_email_private: true keep_pronouns_private: true + pronouns: he/him email_notifications_preference: enabled passwd: ZogKvWdyEx:password passwd_hash_algo: dummy diff --git a/models/forgejo/semver/main_test.go b/models/forgejo/semver/main_test.go index dcc9d588cd..d4c75675ea 100644 --- a/models/forgejo/semver/main_test.go +++ b/models/forgejo/semver/main_test.go @@ -6,11 +6,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" ) func TestMain(m *testing.M) { diff --git a/models/forgejo_migrations/foreign_key_utils.go b/models/forgejo_migrations/foreign_key_utils.go index fc2680e43e..2a792fd66b 100644 --- a/models/forgejo_migrations/foreign_key_utils.go +++ b/models/forgejo_migrations/foreign_key_utils.go @@ -4,28 +4,30 @@ package forgejo_migrations import ( - "errors" + "fmt" "forgejo.org/modules/log" + "xorm.io/builder" "xorm.io/xorm" ) -func syncDoctorForeignKey(x *xorm.Engine, beans []any) error { - for _, bean := range beans { - // Sync() drops indexes by default, which will cause unnecessary rebuilding of indexes when syncDoctorForeignKey - // is used with partial bean definitions; so we disable that option - _, err := x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, bean) - if err != nil { - if errors.Is(err, xorm.ErrForeignKeyViolation) { - tableName := x.TableName(bean) - log.Error( - "Foreign key creation on table %s failed. Run `forgejo doctor check --all` to identify the orphaned records preventing this foreign key from being created. Error was: %v", - tableName, err) - return err - } - return err - } +// syncForeignKeyWithDelete will delete any records that match `cond`, and if present, log and warn to the +// administrator; then it will perform an `xorm.Sync()` in order to create foreign keys on the table definition. +func syncForeignKeyWithDelete(x *xorm.Engine, bean any, cond builder.Cond) error { + rowsDeleted, err := x.Where(cond).Delete(bean) + if err != nil { + return fmt.Errorf("failure to delete inconsistent records before foreign key sync: %w", err) } - return nil + if rowsDeleted > 0 { + tableName := x.TableName(bean) + log.Warn( + "Foreign key creation on table %s required deleting %d records with inconsistent foreign key values.", + tableName, rowsDeleted) + } + + // Sync() drops indexes by default, which will cause unnecessary rebuilding of indexes when syncForeignKeyWithDelete + // is used with partial bean definitions; so we disable that option + _, err = x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, bean) + return err } diff --git a/models/forgejo_migrations/v14a_add-foreign-keys-collaboration.go b/models/forgejo_migrations/v14a_add-foreign-keys-collaboration.go index a52e8d6220..774dfe158c 100644 --- a/models/forgejo_migrations/v14a_add-foreign-keys-collaboration.go +++ b/models/forgejo_migrations/v14a_add-foreign-keys-collaboration.go @@ -4,6 +4,7 @@ package forgejo_migrations import ( + "xorm.io/builder" "xorm.io/xorm" ) @@ -19,7 +20,11 @@ func addForeignKeysCollaboration(x *xorm.Engine) error { RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL REFERENCES(repository, id)"` UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL REFERENCES(user, id)"` } - return syncDoctorForeignKey(x, []any{ + return syncForeignKeyWithDelete(x, new(Collaboration), - }) + builder.Or( + builder.Expr("NOT EXISTS (SELECT id FROM repository WHERE repository.id = collaboration.repo_id)"), + builder.Expr("NOT EXISTS (SELECT id FROM `user` WHERE `user`.id = collaboration.user_id)"), + ), + ) } diff --git a/models/forgejo_migrations/v14a_add-foreign-keys-collaboration_test.go b/models/forgejo_migrations/v14a_add-foreign-keys-collaboration_test.go new file mode 100644 index 0000000000..657bdf377a --- /dev/null +++ b/models/forgejo_migrations/v14a_add-foreign-keys-collaboration_test.go @@ -0,0 +1,53 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package forgejo_migrations + +import ( + "testing" + + "forgejo.org/models/db" + migration_tests "forgejo.org/models/gitea_migrations/test" + "forgejo.org/modules/timeutil" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_addForeignKeysCollaboration(t *testing.T) { + type AccessMode int + type Collaboration struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` + UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` + Mode AccessMode `xorm:"DEFAULT 2 NOT NULL"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` + UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` + } + type Repository struct { + ID int64 `xorm:"pk autoincr"` + } + type User struct { + ID int64 `xorm:"pk autoincr"` + } + x, deferable := migration_tests.PrepareTestEnv(t, 0, new(User), new(Repository), new(Collaboration)) + defer deferable() + if x == nil || t.Failed() { + return + } + + require.NoError(t, addForeignKeysCollaboration(x)) + + var remainingRecords []*Collaboration + require.NoError(t, + db.GetEngine(t.Context()). + Table("collaboration"). + Select("`id`, `repo_id`, `user_id`"). + OrderBy("`id`"). + Find(&remainingRecords)) + assert.Equal(t, + []*Collaboration{ + {ID: 1, UserID: 1, RepoID: 1}, + }, + remainingRecords) +} diff --git a/models/forgejo_migrations/v14a_add-foreign-keys-forgejo_auth_token.go b/models/forgejo_migrations/v14a_add-foreign-keys-forgejo_auth_token.go index a5d8126d91..4aea62da50 100644 --- a/models/forgejo_migrations/v14a_add-foreign-keys-forgejo_auth_token.go +++ b/models/forgejo_migrations/v14a_add-foreign-keys-forgejo_auth_token.go @@ -4,6 +4,7 @@ package forgejo_migrations import ( + "xorm.io/builder" "xorm.io/xorm" ) @@ -18,7 +19,8 @@ func addForeignKeysForgejoAuthToken(x *xorm.Engine) error { type ForgejoAuthToken struct { UID int64 `xorm:"INDEX REFERENCES(user, id)"` } - return syncDoctorForeignKey(x, []any{ + return syncForeignKeyWithDelete(x, new(ForgejoAuthToken), - }) + builder.Expr("NOT EXISTS (SELECT id FROM `user` WHERE `user`.id = forgejo_auth_token.uid)"), + ) } diff --git a/models/forgejo_migrations/v14a_add-foreign-keys-forgejo_auth_token_test.go b/models/forgejo_migrations/v14a_add-foreign-keys-forgejo_auth_token_test.go new file mode 100644 index 0000000000..7f01a9ccf3 --- /dev/null +++ b/models/forgejo_migrations/v14a_add-foreign-keys-forgejo_auth_token_test.go @@ -0,0 +1,50 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package forgejo_migrations + +import ( + "testing" + + "forgejo.org/models/db" + migration_tests "forgejo.org/models/gitea_migrations/test" + "forgejo.org/modules/timeutil" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_addForeignKeysForgejoAuthToken(t *testing.T) { + type AuthorizationPurpose string + type ForgejoAuthToken struct { + ID int64 `xorm:"pk autoincr"` + UID int64 `xorm:"INDEX"` + LookupKey string `xorm:"INDEX UNIQUE"` + HashedValidator string + Purpose AuthorizationPurpose `xorm:"NOT NULL DEFAULT 'long_term_authorization'"` + Expiry timeutil.TimeStamp + } + type User struct { + ID int64 `xorm:"pk autoincr"` + } + x, deferable := migration_tests.PrepareTestEnv(t, 0, new(User), new(ForgejoAuthToken)) + defer deferable() + if x == nil || t.Failed() { + return + } + + require.NoError(t, addForeignKeysForgejoAuthToken(x)) + + var remainingRecords []*ForgejoAuthToken + require.NoError(t, + db.GetEngine(t.Context()). + Table("forgejo_auth_token"). + Select("`id`, `uid`"). + OrderBy("`id`"). + Find(&remainingRecords)) + assert.Equal(t, + []*ForgejoAuthToken{ + {ID: 1, UID: 1}, + }, + remainingRecords) +} diff --git a/models/forgejo_migrations/v14a_add-foreign-keys-pull_request-1.go b/models/forgejo_migrations/v14a_add-foreign-keys-pull_request-1.go index 6d262f385f..6e67207c7d 100644 --- a/models/forgejo_migrations/v14a_add-foreign-keys-pull_request-1.go +++ b/models/forgejo_migrations/v14a_add-foreign-keys-pull_request-1.go @@ -4,6 +4,7 @@ package forgejo_migrations import ( + "xorm.io/builder" "xorm.io/xorm" ) @@ -19,7 +20,11 @@ func addForeignKeysPullRequest1(x *xorm.Engine) error { IssueID int64 `xorm:"INDEX REFERENCES(issue, id)"` BaseRepoID int64 `xorm:"INDEX REFERENCES(repository, id)"` } - return syncDoctorForeignKey(x, []any{ + return syncForeignKeyWithDelete(x, new(PullRequest), - }) + builder.Or( + builder.Expr("NOT EXISTS (SELECT id FROM issue WHERE issue.id = pull_request.issue_id)"), + builder.Expr("NOT EXISTS (SELECT id FROM repository WHERE repository.id = pull_request.base_repo_id)"), + ), + ) } diff --git a/models/forgejo_migrations/v14a_add-foreign-keys-pull_request-1_test.go b/models/forgejo_migrations/v14a_add-foreign-keys-pull_request-1_test.go new file mode 100644 index 0000000000..ebe8600350 --- /dev/null +++ b/models/forgejo_migrations/v14a_add-foreign-keys-pull_request-1_test.go @@ -0,0 +1,69 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package forgejo_migrations + +import ( + "testing" + + "forgejo.org/models/db" + migration_tests "forgejo.org/models/gitea_migrations/test" + "forgejo.org/modules/timeutil" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_addForeignKeysPullRequest1(t *testing.T) { + type PullRequestType int + type PullRequestStatus int + type PullRequestFlow int + type PullRequest struct { + ID int64 `xorm:"pk autoincr"` + Type PullRequestType + Status PullRequestStatus + ConflictedFiles []string `xorm:"TEXT JSON"` + CommitsAhead int + CommitsBehind int + ChangedProtectedFiles []string `xorm:"TEXT JSON"` + IssueID int64 `xorm:"INDEX"` + Index int64 + HeadRepoID int64 `xorm:"INDEX"` + BaseRepoID int64 `xorm:"INDEX"` + HeadBranch string + BaseBranch string + MergeBase string `xorm:"VARCHAR(64)"` + AllowMaintainerEdit bool `xorm:"NOT NULL DEFAULT false"` + HasMerged bool `xorm:"INDEX"` + MergedCommitID string `xorm:"VARCHAR(64)"` + MergerID int64 `xorm:"INDEX"` + MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"` + Flow PullRequestFlow `xorm:"NOT NULL DEFAULT 0"` + } + type Repository struct { + ID int64 `xorm:"pk autoincr"` + } + type Issue struct { + ID int64 `xorm:"pk autoincr"` + } + x, deferable := migration_tests.PrepareTestEnv(t, 0, new(Issue), new(Repository), new(PullRequest)) + defer deferable() + if x == nil || t.Failed() { + return + } + + require.NoError(t, addForeignKeysPullRequest1(x)) + + var remainingRecords []*PullRequest + require.NoError(t, + db.GetEngine(t.Context()). + Table("pull_request"). + Select("`id`, `issue_id`, `base_repo_id`"). + OrderBy("`id`"). + Find(&remainingRecords)) + assert.Equal(t, + []*PullRequest{ + {ID: 1, BaseRepoID: 1, IssueID: 1}, + }, + remainingRecords) +} diff --git a/models/forgejo_migrations_legacy/v41.go b/models/forgejo_migrations_legacy/v41.go index 4b3306debd..6dd25486c6 100644 --- a/models/forgejo_migrations_legacy/v41.go +++ b/models/forgejo_migrations_legacy/v41.go @@ -4,7 +4,6 @@ package forgejo_migrations_legacy import ( - "errors" "fmt" "forgejo.org/modules/log" @@ -13,23 +12,24 @@ import ( "xorm.io/xorm" ) -func syncDoctorForeignKey(x *xorm.Engine, beans []any) error { - for _, bean := range beans { - // Sync() drops indexes by default, which will cause unnecessary rebuilding of indexes when syncDoctorForeignKey - // is used with partial bean definitions; so we disable that option - _, err := x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, bean) - if err != nil { - if errors.Is(err, xorm.ErrForeignKeyViolation) { - tableName := x.TableName(bean) - log.Error( - "Foreign key creation on table %s failed. Run `forgejo doctor check --all` to identify the orphaned records preventing this foreign key from being created. Error was: %v", - tableName, err) - return err - } - return err - } +// syncForeignKeyWithDelete will delete any records that match `cond`, and if present, log and warn to the +// administrator; then it will perform an `xorm.Sync()` in order to create foreign keys on the table definition. +func syncForeignKeyWithDelete(x *xorm.Engine, bean any, cond builder.Cond) error { + rowsDeleted, err := x.Where(cond).Delete(bean) + if err != nil { + return fmt.Errorf("failure to delete inconsistent records before foreign key sync: %w", err) } - return nil + if rowsDeleted > 0 { + tableName := x.TableName(bean) + log.Warn( + "Foreign key creation on table %s required deleting %d records with inconsistent foreign key values.", + tableName, rowsDeleted) + } + + // Sync() drops indexes by default, which will cause unnecessary rebuilding of indexes when syncForeignKeyWithDelete + // is used with partial bean definitions; so we disable that option + _, err = x.SyncWithOptions(xorm.SyncOptions{IgnoreDropIndices: true}, bean) + return err } func AddForeignKeysStopwatchTrackedTime(x *xorm.Engine) error { @@ -50,6 +50,7 @@ func AddForeignKeysStopwatchTrackedTime(x *xorm.Engine) error { err := x.Table("tracked_time"). Join("LEFT", "`user`", "`tracked_time`.user_id = `user`.id"). Where(builder.IsNull{"`user`.id"}). + Where(builder.NotNull{"tracked_time.user_id"}). Find(&trackedTime) if err != nil { return err @@ -63,8 +64,25 @@ func AddForeignKeysStopwatchTrackedTime(x *xorm.Engine) error { } } - return syncDoctorForeignKey(x, []any{ + err = syncForeignKeyWithDelete(x, new(Stopwatch), + builder.Or( + builder.Expr("NOT EXISTS (SELECT id FROM issue WHERE issue.id = stopwatch.issue_id)"), + builder.Expr("NOT EXISTS (SELECT id FROM `user` WHERE `user`.id = stopwatch.user_id)"), + ), + ) + if err != nil { + return err + } + + return syncForeignKeyWithDelete(x, new(TrackedTime), - }) + builder.Or( + builder.And( + builder.Expr("user_id IS NOT NULL"), + builder.Expr("NOT EXISTS (SELECT id FROM `user` WHERE `user`.id = tracked_time.user_id)"), + ), + builder.Expr("NOT EXISTS (SELECT id FROM issue WHERE issue.id = tracked_time.issue_id)"), + ), + ) } diff --git a/models/forgejo_migrations_legacy/v41_test.go b/models/forgejo_migrations_legacy/v41_test.go new file mode 100644 index 0000000000..47fc7f582e --- /dev/null +++ b/models/forgejo_migrations_legacy/v41_test.go @@ -0,0 +1,75 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package forgejo_migrations_legacy + +import ( + "testing" + + "forgejo.org/models/db" + migration_tests "forgejo.org/models/gitea_migrations/test" + "forgejo.org/modules/timeutil" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_AddForeignKeysStopwatchTrackedTime(t *testing.T) { + type Stopwatch struct { + ID int64 `xorm:"pk autoincr"` + IssueID int64 `xorm:"INDEX"` + UserID int64 `xorm:"INDEX"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + } + type TrackedTime struct { + ID int64 `xorm:"pk autoincr"` + IssueID int64 `xorm:"INDEX"` + UserID int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"created"` + Time int64 `xorm:"NOT NULL"` + Deleted bool `xorm:"NOT NULL DEFAULT false"` + } + type User struct { + ID int64 `xorm:"pk autoincr"` + } + type Issue struct { + ID int64 `xorm:"pk autoincr"` + } + x, deferable := migration_tests.PrepareTestEnv(t, 0, new(User), new(Issue), new(Stopwatch), new(TrackedTime)) + defer deferable() + if x == nil || t.Failed() { + return + } + + require.NoError(t, AddForeignKeysStopwatchTrackedTime(x)) + + var remainingStopwatch []*Stopwatch + require.NoError(t, + db.GetEngine(t.Context()). + Table("stopwatch"). + Select("`id`, `issue_id`, `user_id`"). + OrderBy("`id`"). + Find(&remainingStopwatch)) + assert.Equal(t, + []*Stopwatch{ + {1, 1, 1, 0}, + }, + remainingStopwatch, + "stopwatch") + + var remainingTrackedTime []*TrackedTime + require.NoError(t, + db.GetEngine(t.Context()). + Table("tracked_time"). + Select("`id`, `issue_id`, `user_id`"). + OrderBy("`id`"). + Find(&remainingTrackedTime)) + assert.Equal(t, + []*TrackedTime{ + {ID: 1, IssueID: 1, UserID: 1}, + {ID: 4, IssueID: 1, UserID: 0}, + {ID: 5, IssueID: 1, UserID: 0}, + }, + remainingTrackedTime, + "tracked_time") +} diff --git a/models/forgejo_migrations_legacy/v44.go b/models/forgejo_migrations_legacy/v44.go index 459c7ac29d..9f2fcef4f4 100644 --- a/models/forgejo_migrations_legacy/v44.go +++ b/models/forgejo_migrations_legacy/v44.go @@ -4,6 +4,7 @@ package forgejo_migrations_legacy import ( + "xorm.io/builder" "xorm.io/xorm" ) @@ -12,7 +13,11 @@ func AddForeignKeysAccess(x *xorm.Engine) error { UserID int64 `xorm:"UNIQUE(s) REFERENCES(user, id)"` RepoID int64 `xorm:"UNIQUE(s) REFERENCES(repository, id)"` } - return syncDoctorForeignKey(x, []any{ + return syncForeignKeyWithDelete(x, new(Access), - }) + builder.Or( + builder.Expr("NOT EXISTS (SELECT id FROM repository WHERE repository.id = access.repo_id)"), + builder.Expr("NOT EXISTS (SELECT id FROM `user` WHERE `user`.id = access.user_id)"), + ), + ) } diff --git a/models/forgejo_migrations_legacy/v44_test.go b/models/forgejo_migrations_legacy/v44_test.go new file mode 100644 index 0000000000..e78aa2fe46 --- /dev/null +++ b/models/forgejo_migrations_legacy/v44_test.go @@ -0,0 +1,50 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package forgejo_migrations_legacy + +import ( + "testing" + + "forgejo.org/models/db" + migration_tests "forgejo.org/models/gitea_migrations/test" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_AddForeignKeysAccess(t *testing.T) { + type AccessMode int + type Access struct { + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"UNIQUE(s)"` + RepoID int64 `xorm:"UNIQUE(s)"` + Mode AccessMode + } + type User struct { + ID int64 `xorm:"pk autoincr"` + } + type Repository struct { + ID int64 `xorm:"pk autoincr"` + } + x, deferable := migration_tests.PrepareTestEnv(t, 0, new(User), new(Repository), new(Access)) + defer deferable() + if x == nil || t.Failed() { + return + } + + require.NoError(t, AddForeignKeysAccess(x)) + + var remainingRecords []*Access + require.NoError(t, + db.GetEngine(t.Context()). + Table("access"). + Select("`id`, `user_id`, `repo_id`"). + OrderBy("`id`"). + Find(&remainingRecords)) + assert.Equal(t, + []*Access{ + {ID: 1, UserID: 1, RepoID: 1}, + }, + remainingRecords) +} diff --git a/models/git/TestCleanupCommitStatus/commit_status.yml b/models/git/TestCleanupCommitStatus/commit_status.yml new file mode 100644 index 0000000000..e62b39b6d2 --- /dev/null +++ b/models/git/TestCleanupCommitStatus/commit_status.yml @@ -0,0 +1,135 @@ +# Fields that should, if changed, prevent deletion: repo_id, sha, context, state, description. The first test sets will +# be varying each of these fields independently to confirm they're kept. + + +# Vary description: +- + id: 10 + index: 1 + repo_id: 62 + state: "pending" + sha: "01" + description: "Waiting for wake up" + context: deploy/awesomeness +- + id: 11 + index: 2 + repo_id: 62 + state: "pending" + sha: "01" + description: "Almost woke up..." + context: deploy/awesomeness + +# Vary state: +- + id: 12 + index: 1 + repo_id: 62 + state: "pending" + sha: "02" + description: "Waiting for wake up" + context: deploy/awesomeness +- + id: 13 + index: 2 + repo_id: 62 + state: "success" + sha: "02" + description: "Waiting for wake up" + context: deploy/awesomeness + +# Vary context: +- + id: 14 + index: 1 + repo_id: 62 + state: "pending" + sha: "03" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 +- + id: 15 + index: 2 + repo_id: 62 + state: "pending" + sha: "03" + description: "Waiting for wake up" + context: deploy/awesomeness-v2 + +# Vary sha: +- + id: 16 + index: 1 + repo_id: 62 + state: "pending" + sha: "04" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 +- + id: 17 + index: 2 + repo_id: 62 + state: "pending" + sha: "05" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 + +# Vary Repo ID: +- + id: 18 + index: 1 + repo_id: 62 + state: "pending" + sha: "06" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 +- + id: 19 + index: 2 + repo_id: 63 + state: "pending" + sha: "06" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 + +# That's all the varying cases, now here's the data that should be affected by the delete: +- + id: 20 + index: 1 + repo_id: 62 + state: "pending" + sha: "07" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 +- # Dupe 1 + id: 21 + index: 2 + repo_id: 62 + state: "pending" + sha: "07" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 +- # Dupe 2 + id: 22 + index: 3 + repo_id: 62 + state: "pending" + sha: "07" + description: "Waiting for wake up" + context: deploy/awesomeness-v1 +- # Switched to "success", keep + id: 23 + index: 4 + repo_id: 62 + state: "success" + sha: "07" + description: "Successful!" + context: deploy/awesomeness-v1 +- # Dupe reporting success again + id: 24 + index: 5 + repo_id: 62 + state: "success" + sha: "07" + description: "Successful!" + context: deploy/awesomeness-v1 diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 60a0aa5a4f..4ae926eed6 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -467,3 +467,68 @@ func ParseCommitsWithStatus(ctx context.Context, commits []*git.Commit, repo *re func hashCommitStatusContext(context string) string { return fmt.Sprintf("%x", sha1.Sum([]byte(context))) } + +func CleanupCommitStatus(ctx context.Context, bufferSize, deleteChunkSize int, dryRun bool) error { + startTime := time.Now() + + var lastCommitStatus CommitStatus + deleteTargets := make([]int64, 0, deleteChunkSize) + recordCount := 0 + deleteCount := 0 + + err := db.IterateByKeyset(ctx, + nil, + []string{"repo_id", "sha", "context", "index", "id"}, + bufferSize, + func(ctx context.Context, commitStatus *CommitStatus) error { + if commitStatus.RepoID != lastCommitStatus.RepoID || + commitStatus.SHA != lastCommitStatus.SHA || + commitStatus.Context != lastCommitStatus.Context || + commitStatus.State != lastCommitStatus.State || + commitStatus.Description != lastCommitStatus.Description { + // New context, or changed state/description; keep it, start looking for duplicates of it. + lastCommitStatus = *commitStatus + } else { + // Same context as previous record, and same state -- this record shouldn't have been stored. + deleteTargets = append(deleteTargets, commitStatus.ID) + + if len(deleteTargets) == deleteChunkSize { + // Flush delete chunk + log.Debug("deleting chunk of %d records (dryRun=%v)", len(deleteTargets), dryRun) + if !dryRun { + if err := db.DeleteByIDs[CommitStatus](ctx, deleteTargets...); err != nil { + return err + } + } + deleteCount += len(deleteTargets) + deleteTargets = make([]int64, 0, deleteChunkSize) + } + } + recordCount++ + return nil + }) + if err != nil { + return err + } + + if len(deleteTargets) > 0 { + log.Debug("deleting final chunk of %d records (dryRun=%v)", len(deleteTargets), dryRun) + if !dryRun { + if err := db.DeleteByIDs[CommitStatus](ctx, deleteTargets...); err != nil { + return err + } + } + deleteCount += len(deleteTargets) + } + + duration := time.Since(startTime) + + if dryRun { + log.Info("Reviewed %d records in commit_status, and would delete %d", recordCount, deleteCount) + } else { + log.Info("Reviewed %d records in commit_status, and deleted %d", recordCount, deleteCount) + } + log.Info("Cleanup commit status took %d milliseconds", duration.Milliseconds()) + + return nil +} diff --git a/models/git/commit_status_test.go b/models/git/commit_status_test.go index ce6c0d4673..b5c3690e0f 100644 --- a/models/git/commit_status_test.go +++ b/models/git/commit_status_test.go @@ -244,3 +244,46 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { assert.Equal(t, "compliance/lint-backend", contexts[0]) } } + +func TestCleanupCommitStatus(t *testing.T) { + defer unittest.OverrideFixtures("models/git/TestCleanupCommitStatus")() + require.NoError(t, unittest.PrepareTestDatabase()) + + // No changes after a dry run: + originalCount := unittest.GetCount(t, &git_model.CommitStatus{}) + err := git_model.CleanupCommitStatus(t.Context(), 100, 100, true) + require.NoError(t, err) + countAfterDryRun := unittest.GetCount(t, &git_model.CommitStatus{}) + assert.Equal(t, originalCount, countAfterDryRun) + + // Perform actual cleanup + err = git_model.CleanupCommitStatus(t.Context(), 100, 100, false) + require.NoError(t, err) + + // Varying descriptions + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 10}) + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 11}) + + // Varying state + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 12}) + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 13}) + + // Varying context + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 14}) + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 15}) + + // Varying sha + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 16}) + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 17}) + + // Varying repo ID + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 18}) + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 19}) + + // Expected to remain or be removed from cleanup of fixture data: + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 20}) + unittest.AssertNotExistsBean(t, &git_model.CommitStatus{ID: 21}) + unittest.AssertNotExistsBean(t, &git_model.CommitStatus{ID: 22}) + unittest.AssertExistsAndLoadBean(t, &git_model.CommitStatus{ID: 23}) + unittest.AssertNotExistsBean(t, &git_model.CommitStatus{ID: 24}) +} diff --git a/models/git/main_test.go b/models/git/main_test.go index 63a3c363ab..c0b444db8f 100644 --- a/models/git/main_test.go +++ b/models/git/main_test.go @@ -7,11 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" ) func TestMain(m *testing.M) { diff --git a/models/gitea_migrations/base/db.go b/models/gitea_migrations/base/db.go index 2f70fc0806..d716e05caf 100644 --- a/models/gitea_migrations/base/db.go +++ b/models/gitea_migrations/base/db.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "reflect" - "regexp" "slices" "strings" @@ -363,7 +362,7 @@ func renameTable(sess *xorm.Session, bean any, tableName, tempTableName string, schema := sess.Engine().Dialect().URI().Schema sess.Engine().SetSchema("") - if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE ? || '_id_seq' AND sequence_catalog = ?", tableName, setting.Database.Name).Find(&originalSequences); err != nil { + if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_schema = ? AND (sequence_name LIKE ? || '_id_seq' AND sequence_catalog = ?)", schema, tableName, setting.Database.Name).Find(&originalSequences); err != nil { log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) return err } @@ -392,7 +391,7 @@ func renameTable(sess *xorm.Session, bean any, tableName, tempTableName string, var indices []string sess.Engine().SetSchema("") - if err := sess.Table("pg_indexes").Cols("indexname").Where("tablename = ? ", tableName).Find(&indices); err != nil { + if err := sess.Table("pg_indexes").Cols("indexname").Where("tablename = ? AND schemaname = ?", tableName, schema).Find(&indices); err != nil { log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) return err } @@ -408,7 +407,7 @@ func renameTable(sess *xorm.Session, bean any, tableName, tempTableName string, var sequences []string sess.Engine().SetSchema("") - if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE 'tmp_recreate__' || ? || '_id_seq' AND sequence_catalog = ?", tableName, setting.Database.Name).Find(&sequences); err != nil { + if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_schema = ? AND sequence_name LIKE 'tmp_recreate__' || ? || '_id_seq' AND sequence_catalog = ?", schema, tableName, setting.Database.Name).Find(&sequences); err != nil { log.Error("Unable to rename %s to %s. Error: %v", tempTableName, tableName, err) return err } @@ -469,74 +468,24 @@ func DropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin if err != nil { return err } - if len(indexRes) != 1 { - continue + containsDroppedColumn := false + for _, r := range indexRes { + indexCol := string(r["name"]) + if slices.Contains(columnNames, indexCol) { + containsDroppedColumn = true + break + } } - indexColumn := string(indexRes[0]["name"]) - for _, name := range columnNames { - if name == indexColumn { - _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s`", indexName)) - if err != nil { - return err - } + if containsDroppedColumn { + if _, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s`", indexName)); err != nil { + return err } } } - - // Here we need to get the columns from the original table - sql := fmt.Sprintf("SELECT sql FROM sqlite_master WHERE tbl_name='%s' and type='table'", tableName) - res, err := sess.Query(sql) - if err != nil { - return err - } - tableSQL := string(res[0]["sql"]) - - // Get the string offset for column definitions: `CREATE TABLE ( column-definitions... )` - columnDefinitionsIndex := strings.Index(tableSQL, "(") - if columnDefinitionsIndex < 0 { - return errors.New("couldn't find column definitions") - } - - // Separate out the column definitions - tableSQL = tableSQL[columnDefinitionsIndex:] - - // Remove the required columnNames - for _, name := range columnNames { - tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*?[,)]").ReplaceAllString(tableSQL, "") - } - - // Ensure the query is ended properly - tableSQL = strings.TrimSpace(tableSQL) - if tableSQL[len(tableSQL)-1] != ')' { - if tableSQL[len(tableSQL)-1] == ',' { - tableSQL = tableSQL[:len(tableSQL)-1] + for _, col := range columnNames { + if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` DROP COLUMN `%s`", tableName, col)); err != nil { + return fmt.Errorf("drop table `%s` column %s encountered error: %w", tableName, col, err) } - tableSQL += ")" - } - - // Find all the columns in the table - columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1) - - tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL - if _, err := sess.Exec(tableSQL); err != nil { - return err - } - - // Now restore the data - columnsSeparated := strings.Join(columns, ",") - insertSQL := fmt.Sprintf("INSERT INTO `new_%s_new` (%s) SELECT %s FROM %s", tableName, columnsSeparated, columnsSeparated, tableName) - if _, err := sess.Exec(insertSQL); err != nil { - return err - } - - // Now drop the old table - if _, err := sess.Exec(fmt.Sprintf("DROP TABLE `%s`", tableName)); err != nil { - return err - } - - // Rename the table - if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `new_%s_new` RENAME TO `%s`", tableName, tableName)); err != nil { - return err } case setting.Database.Type.IsPostgreSQL(): diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/access.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/access.yml new file mode 100644 index 0000000000..8ce770fbd0 --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/access.yml @@ -0,0 +1,28 @@ +- + id: 1 + repo_id: 1 + user_id: 1 + +# Expected to be deleted due to invalid repository foreign key +- + id: 2 + repo_id: 100 + user_id: 1 + +# Expected to be deleted due to null repository foreign key +- + id: 3 + repo_id: null + user_id: 1 + +# Expected to be deleted due to invalid user foreign key +- + id: 4 + repo_id: 1 + user_id: 100 + +# Expected to be deleted due to null user foreign key +- + id: 5 + repo_id: 1 + user_id: null diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/repository.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/repository.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/repository.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/tracked_time.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/tracked_time.yml new file mode 100644 index 0000000000..0be83d55a5 --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/tracked_time.yml @@ -0,0 +1,33 @@ +- + id: 1 + issue_id: 1 + user_id: 1 + time: 100 + +# Expected to be deleted due to invalid issue foreign key +- + id: 2 + issue_id: 100 + user_id: 1 + time: 100 + +# Expected to be deleted due to null issue foreign key +- + id: 3 + issue_id: null + user_id: 1 + time: 100 + +# Expected to be retained with null, due to invalid user foreign key +- + id: 4 + issue_id: 1 + user_id: 100 + time: 100 + +# Expected to be retained with null user foreign key +- + id: 5 + issue_id: 1 + user_id: null + time: 100 diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/user.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/user.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysAccess/user.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/issue.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/issue.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/issue.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/stopwatch.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/stopwatch.yml new file mode 100644 index 0000000000..5d84c3a78d --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/stopwatch.yml @@ -0,0 +1,28 @@ +- + id: 1 + issue_id: 1 + user_id: 1 + +# Expected to be deleted due to invalid issue foreign key +- + id: 2 + issue_id: 100 + user_id: 1 + +# Expected to be deleted due to null issue foreign key +- + id: 3 + issue_id: null + user_id: 1 + +# Expected to be deleted due to invalid user foreign key +- + id: 4 + issue_id: 1 + user_id: 100 + +# Expected to be deleted due to null user foreign key +- + id: 5 + issue_id: 1 + user_id: null diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/tracked_time.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/tracked_time.yml new file mode 100644 index 0000000000..0be83d55a5 --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/tracked_time.yml @@ -0,0 +1,33 @@ +- + id: 1 + issue_id: 1 + user_id: 1 + time: 100 + +# Expected to be deleted due to invalid issue foreign key +- + id: 2 + issue_id: 100 + user_id: 1 + time: 100 + +# Expected to be deleted due to null issue foreign key +- + id: 3 + issue_id: null + user_id: 1 + time: 100 + +# Expected to be retained with null, due to invalid user foreign key +- + id: 4 + issue_id: 1 + user_id: 100 + time: 100 + +# Expected to be retained with null user foreign key +- + id: 5 + issue_id: 1 + user_id: null + time: 100 diff --git a/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/user.yml b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/user.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_AddForeignKeysStopwatchTrackedTime/user.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/collaboration.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/collaboration.yml new file mode 100644 index 0000000000..a96c2340c8 --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/collaboration.yml @@ -0,0 +1,16 @@ +- + id: 1 + user_id: 1 + repo_id: 1 + +# Expected to be deleted due to invalid user_id foreign key +- + id: 2 + user_id: 100 + repo_id: 1 + +# Expected to be deleted due to invalid repo_id foreign key +- + id: 3 + user_id: 1 + repo_id: 100 diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/repository.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/repository.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/repository.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/user.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/user.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysCollaboration/user.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysForgejoAuthToken/forgejo_auth_token.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysForgejoAuthToken/forgejo_auth_token.yml new file mode 100644 index 0000000000..ee151f769e --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysForgejoAuthToken/forgejo_auth_token.yml @@ -0,0 +1,16 @@ +- + id: 1 + uid: 1 + lookup_key: key-1 + +# Expected to be deleted due to invalid user foreign key +- + id: 2 + uid: 100 + lookup_key: key-2 + +# Expected to be deleted due to a null user foreign key +- + id: 3 + uid: null + lookup_key: key-3 diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysForgejoAuthToken/user.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysForgejoAuthToken/user.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysForgejoAuthToken/user.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/issue.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/issue.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/issue.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/pull_request.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/pull_request.yml new file mode 100644 index 0000000000..390bb2ff4d --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/pull_request.yml @@ -0,0 +1,28 @@ +- + id: 1 + issue_id: 1 + base_repo_id: 1 + +# Expected to be deleted due to invalid issue foreign key +- + id: 2 + issue_id: 100 + base_repo_id: 1 + +# Expected to be deleted due to null issue foreign key +- + id: 3 + issue_id: null + base_repo_id: 1 + +# Expected to be deleted due to invalid repository foreign key +- + id: 4 + issue_id: 1 + base_repo_id: 100 + +# Expected to be deleted due to null repository foreign key +- + id: 5 + issue_id: 1 + base_repo_id: null diff --git a/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/repository.yml b/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/repository.yml new file mode 100644 index 0000000000..a88c2ef89f --- /dev/null +++ b/models/gitea_migrations/fixtures/Test_addForeignKeysPullRequest1/repository.yml @@ -0,0 +1,2 @@ +- + id: 1 diff --git a/models/issues/comment.go b/models/issues/comment.go index 06d35bb2d4..769feba54a 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -611,9 +611,13 @@ func (c *Comment) UpdateAttachments(ctx context.Context, uuids []string) error { } defer committer.Close() - attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, uuids) + if err := c.LoadIssue(ctx); err != nil { + return fmt.Errorf("LoadIssue: %w", err) + } + + attachments, err := repo_model.FindRepoAttachmentsByUUID(ctx, c.Issue.RepoID, uuids, repo_model.FindAttachmentOptions{}) if err != nil { - return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", uuids, err) + return fmt.Errorf("FindRepoAttachmentsByUUID[uuids=%q,repoID=%d]: %w", uuids, c.Issue.RepoID, err) } for i := 0; i < len(attachments); i++ { attachments[i].IssueID = c.IssueID @@ -889,7 +893,7 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment // Check comment type. switch opts.Type { case CommentTypeCode: - if err = updateAttachments(ctx, opts, comment); err != nil { + if err := comment.UpdateAttachments(ctx, opts.Attachments); err != nil { return err } if comment.ReviewID != 0 { @@ -909,7 +913,7 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment } fallthrough case CommentTypeReview: - if err = updateAttachments(ctx, opts, comment); err != nil { + if err := comment.UpdateAttachments(ctx, opts.Attachments); err != nil { return err } case CommentTypeReopen, CommentTypeClose: @@ -921,23 +925,6 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment return UpdateIssueCols(ctx, opts.Issue, "updated_unix") } -func updateAttachments(ctx context.Context, opts *CreateCommentOptions, comment *Comment) error { - attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, opts.Attachments) - if err != nil { - return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", opts.Attachments, err) - } - for i := range attachments { - attachments[i].IssueID = opts.Issue.ID - attachments[i].CommentID = comment.ID - // No assign value could be 0, so ignore AllCols(). - if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Update(attachments[i]); err != nil { - return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err) - } - } - comment.Attachments = attachments - return nil -} - func createDeadlineComment(ctx context.Context, doer *user_model.User, issue *Issue, newDeadlineUnix timeutil.TimeStamp) (*Comment, error) { var content string var commentType CommentType diff --git a/models/issues/issue_update.go b/models/issues/issue_update.go index 84a8820cd1..22e6fcb8d4 100644 --- a/models/issues/issue_update.go +++ b/models/issues/issue_update.go @@ -234,18 +234,18 @@ func AddDeletePRBranchComment(ctx context.Context, doer *user_model.User, repo * } // UpdateIssueAttachments update attachments by UUIDs for the issue -func UpdateIssueAttachments(ctx context.Context, issueID int64, uuids []string) (err error) { +func UpdateIssueAttachments(ctx context.Context, issue *Issue, uuids []string) (err error) { ctx, committer, err := db.TxContext(ctx) if err != nil { return err } defer committer.Close() - attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, uuids) + attachments, err := repo_model.FindRepoAttachmentsByUUID(ctx, issue.RepoID, uuids, repo_model.FindAttachmentOptions{}) if err != nil { - return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", uuids, err) + return fmt.Errorf("FindRepoAttachmentsByUUID[uuids=%q,repoID=%d]: %w", uuids, issue.RepoID, err) } for i := 0; i < len(attachments); i++ { - attachments[i].IssueID = issueID + attachments[i].IssueID = issue.ID if err := repo_model.UpdateAttachment(ctx, attachments[i]); err != nil { return fmt.Errorf("update attachment [id: %d]: %w", attachments[i].ID, err) } @@ -394,18 +394,8 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue return err } - if len(opts.Attachments) > 0 { - attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, opts.Attachments) - if err != nil { - return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %w", opts.Attachments, err) - } - - for i := 0; i < len(attachments); i++ { - attachments[i].IssueID = opts.Issue.ID - if _, err = e.ID(attachments[i].ID).Update(attachments[i]); err != nil { - return fmt.Errorf("update attachment [id: %d]: %w", attachments[i].ID, err) - } - } + if err := UpdateIssueAttachments(ctx, opts.Issue, opts.Attachments); err != nil { + return fmt.Errorf("UpdateIssueAttachments: %w", err) } if err = opts.Issue.LoadAttributes(ctx); err != nil { return err diff --git a/models/issues/main_test.go b/models/issues/main_test.go index 05d854c964..c4057df9cc 100644 --- a/models/issues/main_test.go +++ b/models/issues/main_test.go @@ -9,12 +9,6 @@ import ( issues_model "forgejo.org/models/issues" "forgejo.org/models/unittest" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/repo" - _ "forgejo.org/models/user" - "github.com/stretchr/testify/require" ) diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go index ddb813cf44..38325e181f 100644 --- a/models/issues/pull_list.go +++ b/models/issues/pull_list.go @@ -63,7 +63,7 @@ func GetUnmergedPullRequestsByHeadInfoMax(ctx context.Context, repoID, olderThan } // GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged -func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) { +func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) (PullRequestList, error) { prs := make([]*PullRequest, 0, 2) sess := db.GetEngine(ctx). Join("INNER", "issue", "issue.id = pull_request.issue_id"). @@ -82,18 +82,44 @@ func CanMaintainerWriteToBranch(ctx context.Context, p access_model.Permission, } prs, err := GetUnmergedPullRequestsByHeadInfo(ctx, p.Units[0].RepoID, branch) + // All these error cases return `false` to defer to the safer choice of not allowing write access on an error. if err != nil { + log.Error("GetUnmergedPullRequestsByHeadInfo failed: %s", err) + return false + } else if issues, err := prs.LoadIssues(ctx); err != nil { + log.Error("LoadIssues failed: %s", err) + return false + } else if err := issues.LoadPosters(ctx); err != nil { + log.Error("LoadPosters failed: %s", err) + return false + } else if err := prs.LoadHeadRepos(ctx); err != nil { + log.Error("LoadHeadRepos failed: %s", err) return false } for _, pr := range prs { if pr.AllowMaintainerEdit { + // PR Poster must have write access to the head, so that when they turned on "AllowMaintainerEdit" they + // delegated that write access to the maintainers of the PR base. If they don't currently have write + // access, they can't delegate that access. + poster := pr.Issue.Poster + posterHeadPerm, err := access_model.GetUserRepoPermission(ctx, pr.HeadRepo, poster) + if err != nil { + log.Error("GetUserRepoPermission failed: %s", err) + continue + } + if !posterHeadPerm.CanWrite(unit.TypeCode) { + continue + } + err = pr.LoadBaseRepo(ctx) if err != nil { + log.Error("LoadBaseRepo failed: %s", err) continue } prPerm, err := access_model.GetUserRepoPermission(ctx, pr.BaseRepo, user) if err != nil { + log.Error("GetUserRepoPermission failed: %s", err) continue } if prPerm.CanWrite(unit.TypeCode) { @@ -240,6 +266,25 @@ func (prs PullRequestList) LoadIssues(ctx context.Context) (IssueList, error) { return issueList, nil } +func (prs PullRequestList) LoadHeadRepos(ctx context.Context) error { + repoIDs := []int64{} + for _, pr := range prs { + repoIDs = append(repoIDs, pr.HeadRepoID) + } + repos, err := db.GetByIDs(ctx, "id", repoIDs, &repo_model.Repository{}) + if err != nil { + return err + } + for _, pr := range prs { + repo, ok := repos[pr.HeadRepoID] + if !ok { + return fmt.Errorf("unable to find repo %d", pr.HeadRepoID) + } + pr.HeadRepo = repo + } + return nil +} + // GetIssueIDs returns all issue ids func (prs PullRequestList) GetIssueIDs() []int64 { return container.FilterSlice(prs, func(pr *PullRequest) (int64, bool) { diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go index d229d83470..e083f6e1e8 100644 --- a/models/issues/tracked_time.go +++ b/models/issues/tracked_time.go @@ -148,7 +148,7 @@ func (opts *FindTrackedTimesOptions) toSession(e db.Engine) db.Engine { // GetTrackedTimes returns all tracked times that fit to the given options. func GetTrackedTimes(ctx context.Context, options *FindTrackedTimesOptions) (trackedTimes TrackedTimeList, err error) { - err = options.toSession(db.GetEngine(ctx)).Find(&trackedTimes) + err = options.toSession(db.GetEngine(ctx)).Asc("tracked_time.id").Find(&trackedTimes) return trackedTimes, err } diff --git a/models/main_test.go b/models/main_test.go index 0edcf8f49d..1e4efb46e4 100644 --- a/models/main_test.go +++ b/models/main_test.go @@ -12,10 +12,6 @@ import ( "forgejo.org/models/unittest" user_model "forgejo.org/models/user" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/system" - "github.com/stretchr/testify/require" ) diff --git a/models/organization/main_test.go b/models/organization/main_test.go index dd10b60d30..5951e06299 100644 --- a/models/organization/main_test.go +++ b/models/organization/main_test.go @@ -8,13 +8,7 @@ import ( "forgejo.org/models/unittest" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/organization" - _ "forgejo.org/models/repo" - _ "forgejo.org/models/user" + _ "forgejo.org/modules/testimport" ) func TestMain(m *testing.M) { diff --git a/models/packages/debian/search_test.go b/models/packages/debian/search_test.go index 43cca6c4bd..15e454afc0 100644 --- a/models/packages/debian/search_test.go +++ b/models/packages/debian/search_test.go @@ -14,11 +14,6 @@ import ( "forgejo.org/modules/packages" packages_service "forgejo.org/services/packages" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/models/packages/main_test.go b/models/packages/main_test.go index f9083d705d..35c37d4072 100644 --- a/models/packages/main_test.go +++ b/models/packages/main_test.go @@ -7,11 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" ) func TestMain(m *testing.M) { diff --git a/models/perm/access/main_test.go b/models/perm/access/main_test.go index 0c27d022e0..6ae18dbf5e 100644 --- a/models/perm/access/main_test.go +++ b/models/perm/access/main_test.go @@ -7,13 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/repo" - _ "forgejo.org/models/user" ) func TestMain(m *testing.M) { diff --git a/models/project/main_test.go b/models/project/main_test.go index eaa13bf309..55073c628d 100644 --- a/models/project/main_test.go +++ b/models/project/main_test.go @@ -7,8 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models/repo" ) func TestMain(m *testing.M) { diff --git a/models/project/project.go b/models/project/project.go index 18c647c8ac..7d507b358d 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -309,6 +309,18 @@ func GetProjectForRepoByID(ctx context.Context, repoID, id int64) (*Project, err return p, nil } +// GetProjectForUserByID returns the project by id that belongs to the specified user. +func GetProjectForUserByID(ctx context.Context, uid, id int64) (*Project, error) { + p := new(Project) + has, err := db.GetEngine(ctx).Where("id=? AND owner_id=?", id, uid).Get(p) + if err != nil { + return nil, err + } else if !has { + return nil, ErrProjectNotExist{ID: id} + } + return p, nil +} + // UpdateProject updates project properties func UpdateProject(ctx context.Context, p *Project) error { if !IsCardTypeValid(p.CardType) { @@ -346,42 +358,26 @@ func updateRepositoryProjectCount(ctx context.Context, repoID int64) error { return nil } -// ChangeProjectStatusByRepoIDAndID toggles a project between opened and closed -func ChangeProjectStatusByRepoIDAndID(ctx context.Context, repoID, projectID int64, isClosed bool) error { - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return err - } - defer committer.Close() - - p := new(Project) - - has, err := db.GetEngine(ctx).ID(projectID).Where("repo_id = ?", repoID).Get(p) - if err != nil { - return err - } else if !has { - return ErrProjectNotExist{ID: projectID, RepoID: repoID} - } - - if err := changeProjectStatus(ctx, p, isClosed); err != nil { - return err - } - - return committer.Commit() -} - -func changeProjectStatus(ctx context.Context, p *Project, isClosed bool) error { - p.IsClosed = isClosed - p.ClosedDateUnix = timeutil.TimeStampNow() - count, err := db.GetEngine(ctx).ID(p.ID).Where("repo_id = ? AND is_closed = ?", p.RepoID, !isClosed).Cols("is_closed", "closed_date_unix").Update(p) - if err != nil { - return err - } - if count < 1 { +// ChangeProjectStatus changes the status of the specified project to the state +// specified via the `isClosed` argument. +func ChangeProjectStatus(ctx context.Context, p *Project, isClosed bool) error { + if p.IsClosed == isClosed { return nil } - return updateRepositoryProjectCount(ctx, p.RepoID) + return db.WithTx(ctx, func(ctx context.Context) error { + p.IsClosed = isClosed + p.ClosedDateUnix = timeutil.TimeStampNow() + count, err := db.GetEngine(ctx).ID(p.ID).Cols("is_closed", "closed_date_unix").Update(p) + if err != nil { + return err + } + if count < 1 { + return nil + } + + return updateRepositoryProjectCount(ctx, p.RepoID) + }) } // DeleteProjectByID deletes a project from a repository. if it's not in a database diff --git a/models/project/project_test.go b/models/project/project_test.go index ab23bab0bf..8a50d73ebc 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -1,4 +1,5 @@ // Copyright 2020 The Gitea Authors. All rights reserved. +// Copyright 2026 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package project @@ -7,8 +8,8 @@ import ( "testing" "forgejo.org/models/db" + repo_model "forgejo.org/models/repo" "forgejo.org/models/unittest" - "forgejo.org/modules/timeutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -48,42 +49,6 @@ func TestGetProjects(t *testing.T) { assert.Len(t, projects, 1) } -func TestProject(t *testing.T) { - require.NoError(t, unittest.PrepareTestDatabase()) - - project := &Project{ - Type: TypeRepository, - TemplateType: TemplateTypeBasicKanban, - CardType: CardTypeTextOnly, - Title: "New Project", - RepoID: 1, - CreatedUnix: timeutil.TimeStampNow(), - CreatorID: 2, - } - - require.NoError(t, NewProject(db.DefaultContext, project)) - - _, err := GetProjectByID(db.DefaultContext, project.ID) - require.NoError(t, err) - - // Update project - project.Title = "Updated title" - require.NoError(t, UpdateProject(db.DefaultContext, project)) - - projectFromDB, err := GetProjectByID(db.DefaultContext, project.ID) - require.NoError(t, err) - - assert.Equal(t, project.Title, projectFromDB.Title) - - require.NoError(t, ChangeProjectStatusByRepoIDAndID(db.DefaultContext, project.RepoID, project.ID, true)) - - // Retrieve from DB afresh to check if it is truly closed - projectFromDB, err = GetProjectByID(db.DefaultContext, project.ID) - require.NoError(t, err) - - assert.True(t, projectFromDB.IsClosed) -} - func TestProjectsSort(t *testing.T) { require.NoError(t, unittest.PrepareTestDatabase()) @@ -93,19 +58,19 @@ func TestProjectsSort(t *testing.T) { }{ { sortType: "default", - wants: []int64{1, 3, 2, 6, 5, 4}, + wants: []int64{1, 3, 2, 7, 6, 5, 4}, }, { sortType: "oldest", - wants: []int64{4, 5, 6, 2, 3, 1}, + wants: []int64{4, 5, 6, 7, 2, 3, 1}, }, { sortType: "recentupdate", - wants: []int64{1, 3, 2, 6, 5, 4}, + wants: []int64{1, 3, 2, 7, 6, 5, 4}, }, { sortType: "leastupdate", - wants: []int64{4, 5, 6, 2, 3, 1}, + wants: []int64{4, 5, 6, 7, 2, 3, 1}, }, } @@ -114,11 +79,82 @@ func TestProjectsSort(t *testing.T) { OrderBy: GetSearchOrderByBySortType(tt.sortType), }) require.NoError(t, err) - assert.Equal(t, int64(6), count) - if assert.Len(t, projects, 6) { + assert.Equal(t, int64(7), count) + if assert.Len(t, projects, 7) { for i := range projects { assert.Equal(t, tt.wants[i], projects[i].ID) } } } } + +func TestGetProjectForUserByID(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + found := func(t *testing.T, uid, id int64) { + t.Helper() + + p, err := GetProjectForUserByID(t.Context(), uid, id) + require.NoError(t, err) + if assert.NotNil(t, p) { + assert.Equal(t, id, p.ID) + } + } + + notFound := func(t *testing.T, uid, id int64) { + t.Helper() + + p, err := GetProjectForUserByID(t.Context(), uid, id) + require.ErrorIs(t, err, ErrProjectNotExist{ID: id}) + assert.Nil(t, p) + } + + found(t, 2, 4) + found(t, 2, 5) + found(t, 2, 6) + found(t, 3, 7) + notFound(t, 1, 4) + notFound(t, 1, 5) + notFound(t, 1, 6) + notFound(t, 1, 7) +} + +func TestChangeProjectStatus(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + t.Run("Unchanged", func(t *testing.T) { + project := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) + + require.NoError(t, ChangeProjectStatus(t.Context(), project, project.IsClosed)) + + projectAfter := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) + assert.Equal(t, project.IsClosed, projectAfter.IsClosed) + }) + + t.Run("Normal", func(t *testing.T) { + project := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) + isClosed := !project.IsClosed + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: project.RepoID}) + + require.NoError(t, ChangeProjectStatus(t.Context(), project, isClosed)) + + projectAfter := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) + repoAfter := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: project.RepoID}) + assert.Equal(t, isClosed, projectAfter.IsClosed) + assert.Equal(t, repo.NumProjects, repoAfter.NumProjects) + assert.Equal(t, repo.NumOpenProjects-1, repoAfter.NumOpenProjects) + assert.Equal(t, repo.NumClosedProjects+1, repoAfter.NumClosedProjects) + }) + + t.Run("Invalid ID", func(t *testing.T) { + project := &Project{ID: 1001, RepoID: 1} + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: project.RepoID}) + + require.NoError(t, ChangeProjectStatus(t.Context(), project, true)) + + repoAfter := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: project.RepoID}) + assert.Equal(t, repo.NumProjects, repoAfter.NumProjects) + assert.Equal(t, repo.NumOpenProjects, repoAfter.NumOpenProjects) + assert.Equal(t, repo.NumClosedProjects, repoAfter.NumClosedProjects) + }) +} diff --git a/models/quota/main_test.go b/models/quota/main_test.go index ec0a0e0013..e752ecb690 100644 --- a/models/quota/main_test.go +++ b/models/quota/main_test.go @@ -7,11 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" ) func TestMain(m *testing.M) { diff --git a/models/repo/attachment.go b/models/repo/attachment.go index 6d903be5f8..1b6af572dd 100644 --- a/models/repo/attachment.go +++ b/models/repo/attachment.go @@ -1,4 +1,5 @@ // Copyright 2017 The Gitea Authors. All rights reserved. +// Copyright 2026 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package repo @@ -16,17 +17,30 @@ import ( "forgejo.org/modules/timeutil" "forgejo.org/modules/util" "forgejo.org/modules/validation" + + "xorm.io/builder" ) // Attachment represent a attachment of issue/comment/release. type Attachment struct { - ID int64 `xorm:"pk autoincr"` - UUID string `xorm:"uuid UNIQUE"` - RepoID int64 `xorm:"INDEX"` // this should not be zero - IssueID int64 `xorm:"INDEX"` // maybe zero when creating - ReleaseID int64 `xorm:"INDEX"` // maybe zero when creating - UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added - CommentID int64 `xorm:"INDEX"` + ID int64 `xorm:"pk autoincr"` + // UUID is the public identifier of the attachment, and is used during HTTP + // requests to refer to a specific attachment. + UUID string `xorm:"uuid UNIQUE"` + // UploaderID is always set and non-zero and refers to the user that has + // uploaded this attachment. + UploaderID int64 `xorm:"INDEX DEFAULT 0"` + // RepoID is always set and non-zero and refers to the repository where this + // attachment was uploaded to. + RepoID int64 `xorm:"INDEX"` + // IssueID, ReleaseID and CommentID have multiple possible states: + // - ReleaseID != 0 && IssueID == 0 && CommentID == 0: attached to release with id `ReleaseID`. + // - ReleaseID == 0 && IssueID != 0 && CommentID == 0: attached to the issue with id `IssueID`. + // - ReleaseID == 0 && IssueID != 0 && CommentID != 0: attached to comment with id `CommentID` that is in issue with id `IssueID`. + // All other states should be considered invalid. + IssueID int64 `xorm:"INDEX"` + ReleaseID int64 `xorm:"INDEX"` + CommentID int64 `xorm:"INDEX"` Name string DownloadCount int64 `xorm:"DEFAULT 0"` Size int64 `xorm:"DEFAULT 0"` @@ -73,6 +87,12 @@ func (a *Attachment) DownloadURL() string { return setting.AppURL + "attachments/" + url.PathEscape(a.UUID) } +// IsAttachedToResource returns true if this attachment is attached to a release, +// issue or comment. +func (a *Attachment) IsAttachedToResource() bool { + return a.ReleaseID != 0 || a.IssueID != 0 || a.CommentID != 0 +} + // ErrAttachmentNotExist represents a "AttachmentNotExist" kind of error. type ErrAttachmentNotExist struct { ID int64 @@ -133,15 +153,37 @@ func GetAttachmentByUUID(ctx context.Context, uuid string) (*Attachment, error) return attach, nil } -// GetAttachmentsByUUIDs returns attachment by given UUID list. -func GetAttachmentsByUUIDs(ctx context.Context, uuids []string) ([]*Attachment, error) { +type FindAttachmentOptions struct { + ReleaseID int64 + IssueID int64 + CommentID int64 +} + +func (opts FindAttachmentOptions) ToConds() builder.Cond { + return builder.Eq{"release_id": opts.ReleaseID, "issue_id": opts.IssueID, "comment_id": opts.CommentID} +} + +// FindRepoAttachmentsByUUID always returns attachment that has a UUID that is +// in the given `uuids` argument and is attached to the repository. +// +// The values in `opts` are always as a condition even if they are zero, this +// allows to search for attachments that are not yet attached to any resource by +// specifying a empty struct. +func FindRepoAttachmentsByUUID(ctx context.Context, repoID int64, uuids []string, opts FindAttachmentOptions) ([]*Attachment, error) { + // Nothing to match anyway. if len(uuids) == 0 { return []*Attachment{}, nil } - // Silently drop invalid uuids. + // At maximum nothing is filtered and we get all attachments via the UUID. attachments := make([]*Attachment, 0, len(uuids)) - return attachments, db.GetEngine(ctx).In("uuid", uuids).Find(&attachments) + + err := db.GetEngine(ctx). + Where("repo_id = ?", repoID). + In("uuid", uuids). + And(opts.ToConds()). + Find(&attachments) + return attachments, err } // ExistAttachmentsByUUID returns true if attachment exists with the given UUID diff --git a/models/repo/attachment_test.go b/models/repo/attachment_test.go index 23f4b3799f..2ee4ee91ed 100644 --- a/models/repo/attachment_test.go +++ b/models/repo/attachment_test.go @@ -1,9 +1,12 @@ // Copyright 2017 The Gitea Authors. All rights reserved. +// Copyright 2026 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package repo_test import ( + "cmp" + "slices" "testing" "forgejo.org/models/db" @@ -88,14 +91,67 @@ func TestUpdateAttachment(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{Name: "new_name"}) } -func TestGetAttachmentsByUUIDs(t *testing.T) { +func TestFindRepoAttachmentsByUUID(t *testing.T) { + defer unittest.OverrideFixtures("models/repo/fixtures/TestFindRepoAttachmentsByUUID")() require.NoError(t, unittest.PrepareTestDatabase()) - attachList, err := repo_model.GetAttachmentsByUUIDs(db.DefaultContext, []string{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17", "not-existing-uuid"}) - require.NoError(t, err) - assert.Len(t, attachList, 2) - assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attachList[0].UUID) - assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17", attachList[1].UUID) - assert.Equal(t, int64(1), attachList[0].IssueID) - assert.Equal(t, int64(5), attachList[1].IssueID) + sort := func(x []*repo_model.Attachment) { + slices.SortFunc(x, func(a, b *repo_model.Attachment) int { + return cmp.Compare(a.ID, b.ID) + }) + } + + t.Run("Empty UUIDs", func(t *testing.T) { + attachments, err := repo_model.FindRepoAttachmentsByUUID(t.Context(), 1001, []string{}, repo_model.FindAttachmentOptions{}) + require.NoError(t, err) + assert.Empty(t, attachments) + }) + + t.Run("Wrong repository", func(t *testing.T) { + attachments, err := repo_model.FindRepoAttachmentsByUUID(t.Context(), 1002, []string{"31b6f65e-2745-4e87-b02c-e6bb9890d399", "e19fd169-c2d1-4fd0-a6d5-9658fd4affed", "758e41f6-e3b7-4420-b34f-1920da0858aa"}, repo_model.FindAttachmentOptions{}) + require.NoError(t, err) + assert.Empty(t, attachments) + }) + + t.Run("Not attached", func(t *testing.T) { + attachments, err := repo_model.FindRepoAttachmentsByUUID(t.Context(), 1001, []string{"31b6f65e-2745-4e87-b02c-e6bb9890d399", "e19fd169-c2d1-4fd0-a6d5-9658fd4affed", "758e41f6-e3b7-4420-b34f-1920da0858aa"}, repo_model.FindAttachmentOptions{}) + require.NoError(t, err) + if assert.Len(t, attachments, 1) { + assert.Equal(t, "31b6f65e-2745-4e87-b02c-e6bb9890d399", attachments[0].UUID) + } + }) + + t.Run("Issue", func(t *testing.T) { + attachments, err := repo_model.FindRepoAttachmentsByUUID(t.Context(), 1001, []string{"17bcdb6b-dd84-4da1-b37a-671165402d8d", "e19fd169-c2d1-4fd0-a6d5-9658fd4affed", "774f276e-c85d-488e-b735-7bc07860c756"}, repo_model.FindAttachmentOptions{IssueID: 1001}) + require.NoError(t, err) + sort(attachments) + if assert.Len(t, attachments, 2) { + assert.Equal(t, "17bcdb6b-dd84-4da1-b37a-671165402d8d", attachments[0].UUID) + assert.Equal(t, "e19fd169-c2d1-4fd0-a6d5-9658fd4affed", attachments[1].UUID) + } + }) + + t.Run("Comment", func(t *testing.T) { + attachments, err := repo_model.FindRepoAttachmentsByUUID(t.Context(), 1001, []string{"edf0d986-8a12-447a-a4bb-e9aefead251b", "774f276e-c85d-488e-b735-7bc07860c756", "e19fd169-c2d1-4fd0-a6d5-9658fd4affed"}, repo_model.FindAttachmentOptions{IssueID: 1001, CommentID: 1001}) + require.NoError(t, err) + if assert.Len(t, attachments, 1) { + assert.Equal(t, "edf0d986-8a12-447a-a4bb-e9aefead251b", attachments[0].UUID) + } + + attachments, err = repo_model.FindRepoAttachmentsByUUID(t.Context(), 1001, []string{"edf0d986-8a12-447a-a4bb-e9aefead251b", "774f276e-c85d-488e-b735-7bc07860c756", "e19fd169-c2d1-4fd0-a6d5-9658fd4affed"}, repo_model.FindAttachmentOptions{IssueID: 1001, CommentID: 1002}) + require.NoError(t, err) + if assert.Len(t, attachments, 1) { + assert.Equal(t, "774f276e-c85d-488e-b735-7bc07860c756", attachments[0].UUID) + } + }) + + t.Run("Release", func(t *testing.T) { + attachments, err := repo_model.FindRepoAttachmentsByUUID(t.Context(), 1001, []string{"d2570bab-c843-486f-b7b7-23e011c42815", "758e41f6-e3b7-4420-b34f-1920da0858aa", "e19fd169-c2d1-4fd0-a6d5-9658fd4affed"}, repo_model.FindAttachmentOptions{ReleaseID: 1001}) + require.NoError(t, err) + if assert.Len(t, attachments, 2) { + sort(attachments) + assert.Equal(t, "758e41f6-e3b7-4420-b34f-1920da0858aa", attachments[0].UUID) + assert.Equal(t, "d2570bab-c843-486f-b7b7-23e011c42815", attachments[1].UUID) + } + }) } diff --git a/models/repo/fixtures/TestFindRepoAttachmentsByUUID/attachment.yml b/models/repo/fixtures/TestFindRepoAttachmentsByUUID/attachment.yml new file mode 100644 index 0000000000..934f92d264 --- /dev/null +++ b/models/repo/fixtures/TestFindRepoAttachmentsByUUID/attachment.yml @@ -0,0 +1,116 @@ +- + id: 1001 + uuid: 70d3e7b8-5e46-41eb-bd2d-afaba53056bd + repo_id: 0 + issue_id: 0 + release_id: 0 + uploader_id: 0 + comment_id: 0 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300000 + +- + id: 1002 + uuid: 31b6f65e-2745-4e87-b02c-e6bb9890d399 + repo_id: 1001 + issue_id: 0 + release_id: 0 + uploader_id: 1001 + comment_id: 0 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300001 + +- + id: 1003 + uuid: 03158f6c-487c-4bc5-b24b-10f13e21c2e7 + repo_id: 1001 + issue_id: 0 + release_id: 0 + uploader_id: 1002 + comment_id: 0 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300002 + +- + id: 1004 + uuid: 17bcdb6b-dd84-4da1-b37a-671165402d8d + repo_id: 1001 + issue_id: 1001 + release_id: 0 + uploader_id: 1001 + comment_id: 0 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300003 + +- + id: 1005 + uuid: e19fd169-c2d1-4fd0-a6d5-9658fd4affed + repo_id: 1001 + issue_id: 1001 + release_id: 0 + uploader_id: 1002 + comment_id: 0 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300004 + +- + id: 1006 + uuid: 758e41f6-e3b7-4420-b34f-1920da0858aa + repo_id: 1001 + issue_id: 0 + release_id: 1001 + uploader_id: 1001 + comment_id: 0 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300005 + +- + id: 1007 + uuid: d2570bab-c843-486f-b7b7-23e011c42815 + repo_id: 1001 + issue_id: 0 + release_id: 1001 + uploader_id: 1002 + comment_id: 0 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300006 + +- + id: 1008 + uuid: edf0d986-8a12-447a-a4bb-e9aefead251b + repo_id: 1001 + issue_id: 1001 + release_id: 0 + uploader_id: 1001 + comment_id: 1001 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300007 + +- + id: 1009 + uuid: 774f276e-c85d-488e-b735-7bc07860c756 + repo_id: 1001 + issue_id: 1001 + release_id: 0 + uploader_id: 1002 + comment_id: 1002 + name: attach1 + download_count: 0 + size: 0 + created_unix: 1771300008 diff --git a/models/repo/main_test.go b/models/repo/main_test.go index 9fd1cacc97..3f7ab214fa 100644 --- a/models/repo/main_test.go +++ b/models/repo/main_test.go @@ -8,13 +8,7 @@ import ( "forgejo.org/models/unittest" - _ "forgejo.org/models" // register table model - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/perm/access" // register table model - _ "forgejo.org/models/repo" // register table model - _ "forgejo.org/models/user" // register table model + _ "forgejo.org/modules/testimport" ) func TestMain(m *testing.M) { diff --git a/models/repo/release.go b/models/repo/release.go index 2310de7cb9..a421930d61 100644 --- a/models/repo/release.go +++ b/models/repo/release.go @@ -224,18 +224,14 @@ func UpdateRelease(ctx context.Context, rel *Release) error { } // AddReleaseAttachments adds a release attachments -func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs []string) (err error) { - // Check attachments - attachments, err := GetAttachmentsByUUIDs(ctx, attachmentUUIDs) +func AddReleaseAttachments(ctx context.Context, release *Release, attachmentUUIDs []string) (err error) { + attachments, err := FindRepoAttachmentsByUUID(ctx, release.RepoID, attachmentUUIDs, FindAttachmentOptions{}) if err != nil { - return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %w", attachmentUUIDs, err) + return fmt.Errorf("FindRepoAttachmentsByUUID[uuids=%q,repoID=%d]: %w", attachmentUUIDs, release.RepoID, err) } for i := range attachments { - if attachments[i].ReleaseID != 0 { - return util.NewPermissionDeniedErrorf("release permission denied") - } - attachments[i].ReleaseID = releaseID + attachments[i].ReleaseID = release.ID // No assign value could be 0, so ignore AllCols(). if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Update(attachments[i]); err != nil { return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err) diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index ac7d2b69e3..36fc0c8a5a 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -373,7 +373,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { } // Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate - if opts.OwnerID > 0 { + if opts.OwnerID != 0 { accessCond := builder.NewCond() if !opts.Collaborate.Value() { accessCond = builder.Eq{"owner_id": opts.OwnerID} diff --git a/models/repo/user_repo.go b/models/repo/user_repo.go index 309bfee18f..ca02c1e3f0 100644 --- a/models/repo/user_repo.go +++ b/models/repo/user_repo.go @@ -162,14 +162,12 @@ func GetReviewers(ctx context.Context, repo *Repository, doerID, posterID int64) return users, db.GetEngine(ctx).Where(cond).OrderBy(user_model.GetOrderByName()).Find(&users) } -// GetIssuePostersWithSearch returns users with limit of 30 whose username started with prefix that have authored an issue/pull request for the given repository -// If isShowFullName is set to true, also include full name prefix search -func GetIssuePostersWithSearch(ctx context.Context, repo *Repository, isPull bool, search string, isShowFullName bool) ([]*user_model.User, error) { +// GetIssuePostersWithSearch returns up to 30 users whose username starts with or full_name contains the given search string for the given repository. +func GetIssuePostersWithSearch(ctx context.Context, repo *Repository, isPull bool, search string) ([]*user_model.User, error) { users := make([]*user_model.User, 0, 30) - prefixCond := db.BuildCaseInsensitiveLike("name", search+"%") - if isShowFullName { - prefixCond = db.BuildCaseInsensitiveLike("full_name", "%"+search+"%") - } + prefixCond := builder.Or( + db.BuildCaseInsensitiveLike("name", search+"%"), + db.BuildCaseInsensitiveLike("full_name", "%"+search+"%")) cond := builder.In("`user`.id", builder.Select("poster_id").From("issue").Where( diff --git a/models/repo/watch.go b/models/repo/watch.go index 3fd915e1e7..e5d4b2f90e 100644 --- a/models/repo/watch.go +++ b/models/repo/watch.go @@ -185,6 +185,12 @@ func WatchIfAuto(ctx context.Context, userID, repoID int64, isWrite bool) error // UnwatchRepos will unwatch the user from all given repositories. func UnwatchRepos(ctx context.Context, userID int64, repoIDs []int64) error { - _, err := db.GetEngine(ctx).Where("user_id=?", userID).In("repo_id", repoIDs).Delete(&Watch{}) - return err + // Unfortunatly, we can't simply delete the Watch records because we do watcher counting in the repo relation. + for _, repoID := range repoIDs { + err := WatchRepoMode(ctx, userID, repoID, WatchModeNone) + if err != nil { + return err + } + } + return nil } diff --git a/models/secret/main_test.go b/models/secret/main_test.go index 85bfec0c4f..ccf8b3ba41 100644 --- a/models/secret/main_test.go +++ b/models/secret/main_test.go @@ -7,9 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/activities" ) func TestMain(m *testing.M) { diff --git a/models/system/main_test.go b/models/system/main_test.go index ca2846527a..bd3406b986 100644 --- a/models/system/main_test.go +++ b/models/system/main_test.go @@ -7,12 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" // register models - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/system" // register models of system ) func TestMain(m *testing.M) { diff --git a/models/unittest/mock_http.go b/models/unittest/mock_http.go index c2c12e55ee..b8413104b3 100644 --- a/models/unittest/mock_http.go +++ b/models/unittest/mock_http.go @@ -7,6 +7,7 @@ import ( "bufio" "fmt" "io" + "maps" "net/http" "net/http/httptest" "net/url" @@ -29,7 +30,7 @@ import ( // test data files func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveMode bool) *httptest.Server { mockServerBaseURL := "" - ignoredHeaders := []string{"cf-ray", "server", "date", "report-to", "nel", "x-request-id"} + ignoredHeaders := []string{"cf-ray", "server", "date", "report-to", "nel", "x-request-id", "set-cookie", "x-gitlab-meta"} server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { path := NormalizedFullPath(r.URL) @@ -46,6 +47,7 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM fixturePath = fmt.Sprintf("%s/%s", testDataDir, strings.TrimLeft(r.URL.Path, "/")) } if liveMode { + require.NoError(t, os.MkdirAll(testDataDir, 0o755)) liveURL := fmt.Sprintf("%s%s", liveServerBaseURL, path) request, err := http.NewRequest(r.Method, liveURL, nil) @@ -68,8 +70,8 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM defer fixture.Close() fixtureWriter := bufio.NewWriter(fixture) - for headerName, headerValues := range response.Header { - for _, headerValue := range headerValues { + for _, headerName := range slices.Sorted(maps.Keys(response.Header)) { + for _, headerValue := range response.Header[headerName] { if !slices.Contains(ignoredHeaders, strings.ToLower(headerName)) { _, err := fmt.Fprintf(fixtureWriter, "%s: %s\n", headerName, headerValue) require.NoError(t, err, "writing the header of the HTTP response to the fixture file failed") @@ -91,8 +93,6 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM fixture, err := os.ReadFile(fixturePath) require.NoError(t, err, "missing mock HTTP response: "+fixturePath) - w.WriteHeader(http.StatusOK) - // replace any mention of the live HTTP service by the mocked host stringFixture := strings.ReplaceAll(string(fixture), liveServerBaseURL, mockServerBaseURL) if isGh { @@ -104,10 +104,16 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM for idx, line := range lines { colonIndex := strings.Index(line, ": ") if colonIndex != -1 { - w.Header().Set(line[0:colonIndex], line[colonIndex+2:]) + // Because we modified the body with ReplaceAll() above, we need to + // remove Content-Length. w.Write() should add it back. + header := line[0:colonIndex] + if !strings.EqualFold(header, "Content-Length") { + w.Header().Set(line[0:colonIndex], line[colonIndex+2:]) + } } else { // we reached the end of the headers (empty line), so what follows is the body responseBody := strings.Join(lines[idx+1:], "\n") + w.WriteHeader(http.StatusOK) _, err := w.Write([]byte(responseBody)) require.NoError(t, err, "writing the body of the HTTP response failed") break diff --git a/models/unittest/mock_http_test.go b/models/unittest/mock_http_test.go new file mode 100644 index 0000000000..9ae4592aab --- /dev/null +++ b/models/unittest/mock_http_test.go @@ -0,0 +1,24 @@ +// Copyright 2026 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package unittest + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// NOTE: This is a test of the unittest helper itself +func TestMockWebServer(t *testing.T) { + server := NewMockWebServer(t, "https://example.com", "testdata", false) + defer server.Close() + request, err := http.NewRequest("GET", server.URL+"/", nil) + require.NoError(t, err) + response, err := server.Client().Do(request) + require.NoError(t, err) + assert.Len(t, response.Header["Header"], 1) + assert.Equal(t, "value", response.Header["Header"][0]) +} diff --git a/models/unittest/testdata/GET_%2F b/models/unittest/testdata/GET_%2F new file mode 100644 index 0000000000..8b79a2cd25 --- /dev/null +++ b/models/unittest/testdata/GET_%2F @@ -0,0 +1,3 @@ +Header: value + +bodydata diff --git a/models/user/main_test.go b/models/user/main_test.go index f0dae086e0..902389fe06 100644 --- a/models/user/main_test.go +++ b/models/user/main_test.go @@ -8,11 +8,7 @@ import ( "forgejo.org/models/unittest" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/user" + _ "forgejo.org/modules/testimport" ) func TestMain(m *testing.M) { diff --git a/modules/actions/log.go b/modules/actions/log.go index 5df1f9bec3..c7cb270b18 100644 --- a/modules/actions/log.go +++ b/modules/actions/log.go @@ -61,7 +61,7 @@ func WriteLogs(ctx context.Context, filename string, offset int64, rows []*runne stat, err := f.Stat() if err != nil { - return nil, fmt.Errorf("dbfs Stat %q: %w", name, err) + return nil, fmt.Errorf("WriteLogs(name=%q, offset=%d, len(rows)=%d): dbfs Stat: %w", name, offset, len(rows), err) } if stat.Size() < offset { // If the size is less than offset, refuse to write, or it could result in content holes. diff --git a/modules/activitypub/main_test.go b/modules/activitypub/main_test.go index c46c1759c1..a3f173f408 100644 --- a/modules/activitypub/main_test.go +++ b/modules/activitypub/main_test.go @@ -7,11 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" ) func TestMain(m *testing.M) { diff --git a/modules/activitypub/user_settings_test.go b/modules/activitypub/user_settings_test.go index 475e761e69..f70b39d5ce 100644 --- a/modules/activitypub/user_settings_test.go +++ b/modules/activitypub/user_settings_test.go @@ -11,8 +11,6 @@ import ( user_model "forgejo.org/models/user" "forgejo.org/modules/activitypub" - _ "forgejo.org/models" // https://forum.gitea.com/t/testfixtures-could-not-clean-table-access-no-such-table-access/4137/4 - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/modules/auth/pam/pam.go b/modules/auth/pam/pam.go index a8b608e6be..a801f39a56 100644 --- a/modules/auth/pam/pam.go +++ b/modules/auth/pam/pam.go @@ -7,10 +7,15 @@ package pam import ( "errors" + "fmt" "github.com/msteinert/pam/v2" ) +// ErrInvalidCredentials is returned when PAM reports an authentication +// or account error (wrong password, unknown user, expired account, etc.). +var ErrInvalidCredentials = errors.New("invalid PAM credentials") + // Supported is true when built with PAM var Supported = true @@ -31,10 +36,16 @@ func Auth(serviceName, userName, passwd string) (string, error) { defer t.End() if err = t.Authenticate(0); err != nil { + if errors.Is(err, pam.ErrAuth) || errors.Is(err, pam.ErrUserUnknown) { + return "", fmt.Errorf("%w: %v", ErrInvalidCredentials, err) + } return "", err } if err = t.AcctMgmt(0); err != nil { + if errors.Is(err, pam.ErrAcctExpired) || errors.Is(err, pam.ErrPermDenied) { + return "", fmt.Errorf("%w: %v", ErrInvalidCredentials, err) + } return "", err } diff --git a/modules/auth/pam/pam_stub.go b/modules/auth/pam/pam_stub.go index 3631eeeda7..41993ed701 100644 --- a/modules/auth/pam/pam_stub.go +++ b/modules/auth/pam/pam_stub.go @@ -9,6 +9,10 @@ import ( "errors" ) +// ErrInvalidCredentials is returned when PAM reports an authentication +// or account error (wrong password, unknown user, expired account, etc.). +var ErrInvalidCredentials = errors.New("invalid PAM credentials") + // Supported is false when built without PAM var Supported = false diff --git a/modules/auth/pam/pam_test.go b/modules/auth/pam/pam_test.go index e9b844e955..c155207426 100644 --- a/modules/auth/pam/pam_test.go +++ b/modules/auth/pam/pam_test.go @@ -15,6 +15,6 @@ import ( func TestPamAuth(t *testing.T) { result, err := Auth("gitea", "user1", "false-pwd") require.Error(t, err) - assert.EqualError(t, err, "Authentication failure") + assert.ErrorIs(t, err, ErrInvalidCredentials) assert.Len(t, result, 0) } diff --git a/modules/git/blob.go b/modules/git/blob.go index e2dc624e86..020a591a23 100644 --- a/modules/git/blob.go +++ b/modules/git/blob.go @@ -141,6 +141,28 @@ func (b *Blob) Name() string { return b.name } +// NewReader return a blob-reader which fails immediately with [BlobTooLargeError] if the file is bigger than the limit +func (b *Blob) NewReader(limit int64) (rc io.ReadCloser, actualSize int64, err error) { + actualSize = b.Size() + if actualSize > limit { + return nil, actualSize, BlobTooLargeError{ + Size: actualSize, + Limit: limit, + } + } + r, _, cancel, err := b.newReader() + if err != nil { + return nil, actualSize, err + } + + return &blobReader{ + rd: r, + n: actualSize, + additionalDiscard: 0, + cancel: cancel, + }, actualSize, nil +} + // NewTruncatedReader return a blob-reader which silently truncates when the limit is reached (io.EOF will be returned) func (b *Blob) NewTruncatedReader(limit int64) (rc io.ReadCloser, fullSize int64, err error) { r, fullSize, cancel, err := b.newReader() @@ -168,14 +190,7 @@ func (b BlobTooLargeError) Error() string { // GetContentBase64 Reads the content of the blob and returns it as base64 encoded string. // Returns [BlobTooLargeError] if the (unencoded) content is larger than the limit. func (b *Blob) GetContentBase64(limit int64) (string, error) { - if b.Size() > limit { - return "", BlobTooLargeError{ - Size: b.Size(), - Limit: limit, - } - } - - rc, size, err := b.NewTruncatedReader(limit) + rc, size, err := b.NewReader(limit) if err != nil { return "", err } diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index 98a1930ac2..f97d7b67fa 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -189,7 +189,7 @@ var ( // `useMergebase` is specified then the merge base between `base` and `head` is // used to compare against `head`. func (repo *Repository) GetShortStat(base, head string, useMergebase bool) (numFiles, totalAdditions, totalDeletions int, err error) { - cmd := NewCommand(repo.Ctx, "diff-tree", "--shortstat") + cmd := NewCommand(repo.Ctx, "diff-tree", "--shortstat", "--find-renames") if useMergebase { cmd = cmd.AddArguments("--merge-base") } @@ -211,7 +211,7 @@ func (repo *Repository) GetShortStat(base, head string, useMergebase bool) (numF // GetCommitShortStat returns the number of files, total additions and total deletions the commit has. func (repo *Repository) GetCommitShortStat(commitID string) (numFiles, totalAdditions, totalDeletions int, err error) { - cmd := NewCommand(repo.Ctx, "diff-tree", "--shortstat", "--no-commit-id", "--root").AddDynamicArguments(commitID) + cmd := NewCommand(repo.Ctx, "diff-tree", "--shortstat", "--no-commit-id", "--root", "--find-renames").AddDynamicArguments(commitID) stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path}) if err != nil { return 0, 0, 0, err diff --git a/modules/git/repo_compare_test.go b/modules/git/repo_compare_test.go index fcdc256112..aa8e92e0ea 100644 --- a/modules/git/repo_compare_test.go +++ b/modules/git/repo_compare_test.go @@ -242,6 +242,18 @@ func TestGetCommitShortStat(t *testing.T) { assert.Equal(t, 6, totalAddition) assert.Equal(t, 0, totalDeletions) }) + + t.Run("Renames", func(t *testing.T) { + repo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "renames")) + require.NoError(t, err) + defer repo.Close() + + numFiles, totalAddition, totalDeletions, err := repo.GetCommitShortStat("f667f3a24223414e3bfbe01ab6e445c703ab8e25") + require.NoError(t, err) + assert.Equal(t, 1, numFiles) + assert.Zero(t, totalAddition) + assert.Zero(t, totalDeletions) + }) } func TestGetShortStat(t *testing.T) { @@ -301,6 +313,28 @@ func TestGetShortStat(t *testing.T) { assert.Zero(t, totalAdditions) assert.Zero(t, totalDeletions) }) + + t.Run("Renames", func(t *testing.T) { + repo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "renames")) + require.NoError(t, err) + defer repo.Close() + + t.Run("Only rename", func(t *testing.T) { + numFiles, totalAdditions, totalDeletions, err := repo.GetShortStat("bc40f00489096a7d4090a609a6572f528e1acb76", "f667f3a24223414e3bfbe01ab6e445c703ab8e25", true) + require.NoError(t, err) + assert.Equal(t, 1, numFiles) + assert.Zero(t, totalAdditions) + assert.Zero(t, totalDeletions) + }) + + t.Run("Too much diverged", func(t *testing.T) { + numFiles, totalAdditions, totalDeletions, err := repo.GetShortStat("bc40f00489096a7d4090a609a6572f528e1acb76", "acdee217ada3fea6e503acfb969724cc799fc516", true) + require.NoError(t, err) + assert.Equal(t, 2, numFiles) + assert.Equal(t, 3, totalAdditions) + assert.Equal(t, 1, totalDeletions) + }) + }) } func TestGetMergeBaseSimple(t *testing.T) { diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 4ea97d66eb..3d05657478 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -5,6 +5,7 @@ package git import ( + "errors" "fmt" "io" "net" @@ -19,6 +20,8 @@ import ( "gopkg.in/ini.v1" //nolint:depguard // used to read .gitmodules ) +const MaxGitmodulesFileSize = 64 * 1024 + // GetSubmodule returns the Submodule of a given path func (c *Commit) GetSubmodule(path string, entry *TreeEntry) (Submodule, error) { err := c.readSubmodules() @@ -55,8 +58,12 @@ func (c *Commit) readSubmodules() error { return err } - rc, _, err := entry.Blob().NewTruncatedReader(10 * 1024) + rc, _, err := entry.Blob().NewReader(MaxGitmodulesFileSize) if err != nil { + if errors.As(err, &BlobTooLargeError{}) { + c.submodules = make(map[string]Submodule) + return nil + } return err } defer rc.Close() diff --git a/modules/git/tests/repos/renames/HEAD b/modules/git/tests/repos/renames/HEAD new file mode 100644 index 0000000000..b870d82622 --- /dev/null +++ b/modules/git/tests/repos/renames/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/modules/git/tests/repos/renames/config b/modules/git/tests/repos/renames/config new file mode 100644 index 0000000000..4ea33d92c0 --- /dev/null +++ b/modules/git/tests/repos/renames/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true +[remote "origin"] + url = /home/gusted/Desktop/renames diff --git a/modules/git/tests/repos/renames/objects/info/commit-graph b/modules/git/tests/repos/renames/objects/info/commit-graph new file mode 100644 index 0000000000..383b1bc443 Binary files /dev/null and b/modules/git/tests/repos/renames/objects/info/commit-graph differ diff --git a/modules/git/tests/repos/renames/objects/info/packs b/modules/git/tests/repos/renames/objects/info/packs new file mode 100644 index 0000000000..226626bf64 --- /dev/null +++ b/modules/git/tests/repos/renames/objects/info/packs @@ -0,0 +1,3 @@ +P pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.pack +P pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.pack + diff --git a/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.idx b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.idx new file mode 100644 index 0000000000..7e7196c5c8 Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.idx differ diff --git a/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.mtimes b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.mtimes new file mode 100644 index 0000000000..31e93d8189 Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.mtimes differ diff --git a/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.pack b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.pack new file mode 100644 index 0000000000..880b956c0c Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.pack differ diff --git a/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.rev b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.rev new file mode 100644 index 0000000000..d2a0203abc Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-3c04d9ebf3e2c4620d7142f736b92d739834e2d4.rev differ diff --git a/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.bitmap b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.bitmap new file mode 100644 index 0000000000..43debf60a7 Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.bitmap differ diff --git a/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.idx b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.idx new file mode 100644 index 0000000000..4c69d3a347 Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.idx differ diff --git a/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.pack b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.pack new file mode 100644 index 0000000000..8b808eb5f2 Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.pack differ diff --git a/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.rev b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.rev new file mode 100644 index 0000000000..44f5b3412e Binary files /dev/null and b/modules/git/tests/repos/renames/objects/pack/pack-d1cbea94fcad36c556cd5921e8df7feff7cbbbb2.rev differ diff --git a/modules/git/tests/repos/renames/packed-refs b/modules/git/tests/repos/renames/packed-refs new file mode 100644 index 0000000000..0688fe7613 --- /dev/null +++ b/modules/git/tests/repos/renames/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +acdee217ada3fea6e503acfb969724cc799fc516 refs/heads/main diff --git a/modules/git/tests/repos/renames/refs/heads/.gitkeep b/modules/git/tests/repos/renames/refs/heads/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/httplib/url.go b/modules/httplib/url.go index 32a02e3277..66ea77add7 100644 --- a/modules/httplib/url.go +++ b/modules/httplib/url.go @@ -1,20 +1,26 @@ // Copyright 2023 The Gitea Authors. All rights reserved. +// Copyright 2026 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package httplib import ( "net/url" + "path" "strings" "forgejo.org/modules/setting" ) +// Unfortunately browsers consider a redirect Location with preceding "//", "\\", "/\" and "\/" as meaning redirect to "http(s)://REST_OF_PATH" +// Therefore we should ignore these redirect locations to prevent open redirects. +func isBrowserRedirect(s string) bool { + return len(s) > 1 && (s[0] == '/' || s[0] == '\\') && (s[1] == '/' || s[1] == '\\') +} + // IsRiskyRedirectURL returns true if the URL is considered risky for redirects func IsRiskyRedirectURL(s string) bool { - // Unfortunately browsers consider a redirect Location with preceding "//", "\\", "/\" and "\/" as meaning redirect to "http(s)://REST_OF_PATH" - // Therefore we should ignore these redirect locations to prevent open redirects - if len(s) > 1 && (s[0] == '/' || s[0] == '\\') && (s[1] == '/' || s[1] == '\\') { + if isBrowserRedirect(s) { return true } @@ -23,5 +29,12 @@ func IsRiskyRedirectURL(s string) bool { return true } + // If the path contains `..` then it's still possible this is seen + // as a browser redirect, use `path.Clean` to eliminate each inner `..` + // and then check if that might be a browser redirect. + if strings.Contains(u.Path, "..") { + return isBrowserRedirect(path.Clean(u.Path)) + } + return false } diff --git a/modules/httplib/url_test.go b/modules/httplib/url_test.go index cd2ceac267..0fd59c13a6 100644 --- a/modules/httplib/url_test.go +++ b/modules/httplib/url_test.go @@ -29,7 +29,6 @@ func TestIsRiskyRedirectURL(t *testing.T) { {"/sub/foo", false}, {"http://localhost:3000/sub/foo", false}, {"http://localhost:3000/sub/test?param=false", false}, - // FIXME: should probably be true (would requires resolving references using setting.appURL.ResolveReference(u)) {"/sub/../", false}, {"http://localhost:3000/sub/../", false}, {"/sUb/", false}, @@ -58,10 +57,12 @@ func TestIsRiskyRedirectURL(t *testing.T) { {"://missing protocol scheme", true}, // FIXME: should probably be false {"//localhost:3000/sub/test?param=false", true}, + {"/a/../\\example.com", true}, + {"/a/%2e%2e/\\example.com", true}, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { - assert.Equal(t, tt.want, IsRiskyRedirectURL(tt.input)) + assert.Equal(t, tt.want, IsRiskyRedirectURL(tt.input), tt.input) }) } } @@ -114,6 +115,8 @@ func TestIsRiskyRedirectURLWithoutSubURL(t *testing.T) { {"https://next.forgejo.org", true}, {"//next.forgejo.org/test?param=false", true}, {"//next.forgejo.org/sub/test?param=false", true}, + {"/a/../\\example.com", true}, + {"/a/%2e%2e/\\example.com", true}, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { diff --git a/modules/indexer/code/indexer.go b/modules/indexer/code/indexer.go index f3ed091a30..a3e20e1d5a 100644 --- a/modules/indexer/code/indexer.go +++ b/modules/indexer/code/indexer.go @@ -21,6 +21,7 @@ import ( "forgejo.org/modules/process" "forgejo.org/modules/queue" "forgejo.org/modules/setting" + "forgejo.org/modules/util" ) var ( @@ -182,12 +183,12 @@ func Init() { log.Fatal("PID: %d Unable to initialize the bleve Repository Indexer at path: %s Error: %v", os.Getpid(), setting.Indexer.RepoPath, err) } case "elasticsearch": - log.Info("PID: %d Initializing Repository Indexer at: %s", os.Getpid(), setting.Indexer.RepoConnStr) + log.Info("PID: %d Initializing Repository Indexer at: %s", os.Getpid(), util.SanitizeCredentialURLs(setting.Indexer.RepoConnStr)) defer func() { if err := recover(); err != nil { log.Error("PANIC whilst initializing repository indexer: %v\nStacktrace: %s", err, log.Stack(2)) log.Error("The indexer files are likely corrupted and may need to be deleted") - log.Error("You can completely remove the \"%s\" index to make Forgejo recreate the indexes", setting.Indexer.RepoConnStr) + log.Error("You can completely remove the \"%s\" index to make Forgejo recreate the indexes", util.SanitizeCredentialURLs(setting.Indexer.RepoConnStr)) } }() @@ -197,7 +198,7 @@ func Init() { cancel() (*globalIndexer.Load()).Close() close(waitChannel) - log.Fatal("PID: %d Unable to initialize the elasticsearch Repository Indexer connstr: %s Error: %v", os.Getpid(), setting.Indexer.RepoConnStr, err) + log.Fatal("PID: %d Unable to initialize the elasticsearch Repository Indexer connstr: %s Error: %v", os.Getpid(), util.SanitizeCredentialURLs(setting.Indexer.RepoConnStr), err) } default: diff --git a/modules/indexer/code/indexer_test.go b/modules/indexer/code/indexer_test.go index 97f17b083f..87deaf928b 100644 --- a/modules/indexer/code/indexer_test.go +++ b/modules/indexer/code/indexer_test.go @@ -14,11 +14,6 @@ import ( "forgejo.org/modules/indexer/code/elasticsearch" "forgejo.org/modules/indexer/code/internal" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index d472067cd8..dd7102713c 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -25,6 +25,7 @@ import ( "forgejo.org/modules/process" "forgejo.org/modules/queue" "forgejo.org/modules/setting" + "forgejo.org/modules/util" ) // IndexerMetadata is used to send data to the queue, so it contains only the ids. @@ -100,7 +101,7 @@ func InitIssueIndexer(syncReindex bool) { issueIndexer = elasticsearch.NewIndexer(setting.Indexer.IssueConnStr, setting.Indexer.IssueIndexerName) existed, err = issueIndexer.Init(ctx) if err != nil { - log.Fatal("Unable to issueIndexer.Init with connection %s Error: %v", setting.Indexer.IssueConnStr, err) + log.Fatal("Unable to issueIndexer.Init with connection %s Error: %v", util.SanitizeCredentialURLs(setting.Indexer.IssueConnStr), err) } case "db": issueIndexer = db_index.NewIndexer() @@ -108,7 +109,7 @@ func InitIssueIndexer(syncReindex bool) { issueIndexer = meilisearch.NewIndexer(setting.Indexer.IssueConnStr, setting.Indexer.IssueConnAuth, setting.Indexer.IssueIndexerName) existed, err = issueIndexer.Init(ctx) if err != nil { - log.Fatal("Unable to issueIndexer.Init with connection %s Error: %v", setting.Indexer.IssueConnStr, err) + log.Fatal("Unable to issueIndexer.Init with connection %s Error: %v", util.SanitizeCredentialURLs(setting.Indexer.IssueConnStr), err) } default: log.Fatal("Unknown issue indexer type: %s", setting.Indexer.IssueType) @@ -261,6 +262,19 @@ func DeleteRepoIssueIndexer(ctx context.Context, repoID int64) { } } +// DeleteIssueIndexer deletes a single issue by it's ID +// +// NOTE: This does not perform any DB validation. +// Hence, the issueID does not need to be present in the DB. +func DeleteIssueIndexer(ctx context.Context, issueID int64) { + if err := pushIssueIndexerQueue(ctx, &IndexerMetadata{ + IDs: []int64{issueID}, + IsDelete: true, + }); err != nil { + log.Error("Unable to push deleted issue %d to issue indexer: %v", issueID, err) + } +} + // IsAvailable checks if issue indexer is available func IsAvailable(ctx context.Context) bool { return (*globalIndexer.Load()).Ping(ctx) == nil diff --git a/modules/indexer/issues/indexer_test.go b/modules/indexer/issues/indexer_test.go index 527627e0fc..7d4ffa7f02 100644 --- a/modules/indexer/issues/indexer_test.go +++ b/modules/indexer/issues/indexer_test.go @@ -4,7 +4,11 @@ package issues import ( + "path/filepath" + "slices" + "strings" "testing" + "time" "forgejo.org/models/db" "forgejo.org/models/issues" @@ -12,11 +16,7 @@ import ( "forgejo.org/modules/indexer/issues/internal" "forgejo.org/modules/optional" "forgejo.org/modules/setting" - - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" + "forgejo.org/modules/test" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -29,7 +29,7 @@ func TestMain(m *testing.M) { func TestDBSearchIssues(t *testing.T) { require.NoError(t, unittest.PrepareTestDatabase()) - setting.Indexer.IssueType = "db" + defer test.MockVariableValue(&setting.Indexer.IssueType, "db")() InitIssueIndexer(true) t.Run("search issues with keyword", searchIssueWithKeyword) @@ -412,3 +412,39 @@ func searchIssueWithPaginator(t *testing.T) { assert.Equal(t, test.expectedTotal, total) } } + +func TestBleveDeleteIssue(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + + tmp := t.TempDir() + defer test.MockVariableValue(&setting.Indexer.IssuePath, filepath.Join(tmp, "indexers/issues.bleve"))() + defer test.MockVariableValue(&setting.Indexer.IssueType, "bleve")() + InitIssueIndexer(false) + + ctx := t.Context() + issue := unittest.AssertExistsAndLoadBean(t, &issues.Issue{ID: 1}) + UpdateIssueIndexer(ctx, issue.ID) + + opts := &internal.SearchOptions{ + RepoIDs: []int64{issue.RepoID}, + } + opts.WithKeyword(ctx, "first") + + assert.Eventually(t, func() bool { + ids, _, err := SearchIssues(ctx, opts) + if err != nil && strings.Contains(err.Error(), "not ready") { + return false + } + assert.NoError(t, err) + + assert.NoError(t, err) + return slices.Contains(ids, issue.ID) + }, time.Second*5, time.Millisecond*100, "failed to update issue") + + DeleteIssueIndexer(ctx, issue.ID) + assert.Eventually(t, func() bool { + ids, _, err := SearchIssues(ctx, opts) + assert.NoError(t, err) + return !slices.Contains(ids, issue.ID) + }, time.Second*5, time.Millisecond*100, "failed to delete issue") +} diff --git a/modules/indexer/stats/indexer_test.go b/modules/indexer/stats/indexer_test.go index a5899d2506..7d51d3f522 100644 --- a/modules/indexer/stats/indexer_test.go +++ b/modules/indexer/stats/indexer_test.go @@ -13,11 +13,6 @@ import ( "forgejo.org/modules/queue" "forgejo.org/modules/setting" - _ "forgejo.org/models" - _ "forgejo.org/models/actions" - _ "forgejo.org/models/activities" - _ "forgejo.org/models/forgefed" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/modules/markup/html.go b/modules/markup/html.go index 2fe0caa5b6..2d569725d7 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -46,6 +46,9 @@ var ( // valid chars in encoded path and parameter: [-+~_%.a-zA-Z0-9/] + // httpSchemePattern matches https:// or http:// + httpSchemePattern = regexp.MustCompile(`^https?://`) + // hashCurrentPattern matches string that represents a commit SHA, e.g. d8a994ef243349f321568f9e36d5c3f444b99cae // Although SHA1 hashes are 40 chars long, SHA256 are 64, the regex matches the hash from 7 to 64 chars in length // so that abbreviated hash links can be used as well. This matches git and GitHub usability. @@ -72,7 +75,7 @@ var ( // https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type%3Demail) emailRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\s|$|\\)|\\]|;|,|\\?|!|\\.(\\s|$))") - // Fediverse handle regex (same as emailRegex but with additonal @ or ! + // Fediverse handle regex (same as emailRegex but with additional @ or ! // at start) fediRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([@!]([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+)@([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+))(?:\\s|$|\\)|\\]|;|,|\\?|!|\\.(\\s|$))") @@ -826,10 +829,7 @@ func pullReviewCommitPatternProcessor(ctx *RenderContext, node *html.Node) { text := "!" + id + " (commit " - baseURLEnd := strings.Index(urlFull, repoSlug) + len(repoSlug) - if len(ctx.Links.Base) > 0 && !strings.HasPrefix(ctx.Links.Base, urlFull[:baseURLEnd]) { - text = repoSlug + "@" + text - } + optionalRepoSlugAndInstancePath(ctx, &text, urlFull, repoSlug) aNode.AppendChild(&html.Node{ Type: html.TextNode, @@ -1083,10 +1083,7 @@ func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) { // We need to figure out the base of the provided URL, which is up to and including the // `/` slug. // With that we can determine if it matches the current repo, or if the slug should be shown. - baseURLEnd := strings.Index(urlFull, repoSlug) + len(repoSlug) - if len(ctx.Links.Base) > 0 && !strings.HasPrefix(ctx.Links.Base, urlFull[:baseURLEnd]) { - text = repoSlug + "@" + text - } + optionalRepoSlugAndInstancePath(ctx, &text, urlFull, repoSlug) // 3rd capture group matches an optional file path after the SHA filePath := "" @@ -1191,10 +1188,7 @@ func comparePatternProcessor(ctx *RenderContext, node *html.Node) { text := text1 + textDots + text2 - baseURLEnd := strings.Index(urlFull, repoSlug) + len(repoSlug) - if len(ctx.Links.Base) > 0 && !strings.HasPrefix(ctx.Links.Base, urlFull[:baseURLEnd]) { - text = repoSlug + "@" + text - } + optionalRepoSlugAndInstancePath(ctx, &text, urlFull, repoSlug) extra := "" if query != "" { @@ -1525,3 +1519,27 @@ func createDescriptionLink(href, content string) *html.Node { textNode.Parent = linkNode return linkNode } + +// Adds an optional repo slug and optionally the instance domain and URL +// +// The repo slug is added if the link points to a different repo +// The instance domain and sub-path is added if the link points to a different instance +func optionalRepoSlugAndInstancePath(ctx *RenderContext, text *string, fullURL, slug string) { + if len(ctx.Links.Base) > 0 { + // The fullURL is the url to e.g. the commit. The slug is e.g. `forgejo/forgejo`. + // To retrieve the instance domain and sub-path we need to remove the repo slug + slugStart := strings.LastIndex(fullURL, slug) + targetInstance := fullURL[:slugStart] + + // Check if the URL points to a different instance + if setting.AppURL != targetInstance { + // Remove the http scheme for displaying + targetInstance = httpSchemePattern.ReplaceAllString(targetInstance, "") + + *text = targetInstance + slug + "@" + *text + } else if !strings.HasSuffix(strings.TrimSuffix(ctx.Links.Base, "/"), slug) { + // If it is a link to a different repo, but on the same instance only add the repo slug + *text = slug + "@" + *text + } + } +} diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go index 1f717a78ed..752ffeba6f 100644 --- a/modules/markup/html_internal_test.go +++ b/modules/markup/html_internal_test.go @@ -12,6 +12,7 @@ import ( "forgejo.org/modules/git" "forgejo.org/modules/setting" + "forgejo.org/modules/test" "forgejo.org/modules/util" "github.com/stretchr/testify/assert" @@ -19,9 +20,10 @@ import ( ) const ( - TestAppURL = "http://localhost:3000/" - TestOrgRepo = "gogits/gogs" - TestRepoURL = TestAppURL + TestOrgRepo + "/" + TestAppURL = "http://localhost:3000/" + TestOrgRepo = "gogits/gogs" + TestRepoURLWithoutSlash = TestAppURL + TestOrgRepo + TestRepoURL = TestAppURL + TestOrgRepo + "/" ) // externalIssueLink an HTML link to an alphanumeric-style issue @@ -107,7 +109,7 @@ func TestRender_IssueIndexPattern(t *testing.T) { } func TestRender_IssueIndexPattern2(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() // numeric: render inputs with valid mentions test := func(s, expectedFmt, marker string, indices ...int) { @@ -174,7 +176,7 @@ func TestRender_IssueIndexPattern2(t *testing.T) { } func TestRender_IssueIndexPattern3(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() // alphanumeric: render inputs without valid mentions test := func(s string) { @@ -202,7 +204,7 @@ func TestRender_IssueIndexPattern3(t *testing.T) { } func TestRender_IssueIndexPattern4(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() // alphanumeric: render inputs with valid mentions test := func(s, expectedFmt string, names ...string) { @@ -222,7 +224,7 @@ func TestRender_IssueIndexPattern4(t *testing.T) { } func TestRender_IssueIndexPattern5(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() // regexp: render inputs without valid mentions test := func(s, expectedFmt, pattern string, ids, names []string) { @@ -265,7 +267,7 @@ func TestRender_IssueIndexPattern5(t *testing.T) { } func TestRender_IssueIndexPattern_Document(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() metas := map[string]string{ "format": "https://someurl.com/{user}/{repo}/{index}", "user": "someUser", @@ -301,9 +303,9 @@ func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *Rend } func TestRender_AutoLink(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() - test := func(input, expected, base string) { + assert := func(input, expected, base string) { var buffer strings.Builder err := PostProcess(&RenderContext{ Ctx: git.DefaultContext, @@ -330,7 +332,7 @@ func TestRender_AutoLink(t *testing.T) { t.Run("Issue", func(t *testing.T) { // render valid issue URLs - test(util.URLJoin(TestRepoURL, "issues", "3333"), + assert(util.URLJoin(TestRepoURL, "issues", "3333"), numericIssueLink(util.URLJoin(TestRepoURL, "issues"), "ref-issue", 3333, "#"), TestRepoURL) }) @@ -338,81 +340,90 @@ func TestRender_AutoLink(t *testing.T) { t.Run("Commit", func(t *testing.T) { // render valid commit URLs tmp := util.URLJoin(TestRepoURL, "commit", "d8a994ef243349f321568f9e36d5c3f444b99cae") - test(tmp, "d8a994ef24", TestRepoURL) - test(tmp, ""+TestOrgRepo+"@d8a994ef24", "https://localhost/forgejo/forgejo") - test( + assert(tmp, "d8a994ef24", TestRepoURLWithoutSlash) + assert(tmp, ""+TestOrgRepo+"@d8a994ef24", "/forgejo/forgejo") + assert( tmp+"#diff-2", "d8a994ef24 (diff-2)", TestRepoURL, ) - test( + assert( tmp+"#diff-953bb4f01b7c77fa18f0cd54211255051e647dbc", "d8a994ef24 (diff-953bb4f01b)", - TestRepoURL, + TestRepoURLWithoutSlash, ) // render other commit URLs tmp = "https://external-link.gitea.io/go-gitea/gitea/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2" - test(tmp, "d8a994ef24 (diff-2)", "https://external-link.gitea.io/go-gitea/gitea") - test(tmp, "go-gitea/gitea@d8a994ef24 (diff-2)", TestRepoURL) + assert(tmp, "external-link.gitea.io/go-gitea/gitea@d8a994ef24 (diff-2)", TestOrgRepo) + defer test.MockVariableValue(&setting.AppURL, "https://external-link.gitea.io/")() + assert(tmp, "d8a994ef24 (diff-2)", "https://external-link.gitea.io/go-gitea/gitea") - tmp = "http://localhost:3000/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" - test(tmp, "190d949293", "http://localhost:3000/gogits/gogs") - test(tmp, "gogits/gogs@190d949293", "https://external-link.gitea.io/go-gitea/gitea") + tmp = TestAppURL + "gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" + assert(tmp, "localhost:3000/gogits/gogs@190d949293", "https://external-link.gitea.io/go-gitea/gitea") + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() + assert(tmp, "190d949293", "http://localhost:3000/gogits/gogs") tmp = "http://localhost:3000/sub/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" - test(tmp, "190d949293", "http://localhost:3000/sub/gogits/gogs") - test(tmp, "gogits/gogs@190d949293", "http://localhost:3000/gogits/gogs") - test(tmp, "gogits/gogs@190d949293", "https://external-link.gitea.io/go-gitea/gitea") + assert(tmp, "localhost:3000/sub/gogits/gogs@190d949293", TestRepoURLWithoutSlash) + assert(tmp, "localhost:3000/sub/gogits/gogs@190d949293", "https://external-link.gitea.io/go-gitea/gitea") + defer test.MockVariableValue(&setting.AppURL, TestAppURL+"sub/")() + assert(tmp, "190d949293", "http://localhost:3000/sub/gogits/gogs") tmp = "http://localhost:3000/sub1/sub2/sub3/gogits/gogs/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" - test(tmp, "190d949293", "http://localhost:3000/sub1/sub2/sub3/gogits/gogs") - test(tmp, "gogits/gogs@190d949293", "http://localhost:3000/sub1/gogits/gogs") - test(tmp, "gogits/gogs@190d949293", "https://external-link.gitea.io/go-gitea/gitea") + defer test.MockVariableValue(&setting.AppURL, TestAppURL+"sub1/sub2/sub3/")() + assert(tmp, "190d949293", "http://localhost:3000/sub1/sub2/sub3/gogits/gogs") + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() + assert(tmp, "localhost:3000/sub1/sub2/sub3/gogits/gogs@190d949293", "http://localhost:3000/sub1/gogits/gogs") + assert(tmp, "localhost:3000/sub1/sub2/sub3/gogits/gogs@190d949293", "https://external-link.gitea.io/go-gitea/gitea") // if the repository happens to be named like one of the known app routes (e.g. `src`), // we can parse the URL correctly, if there is no sub path tmp = "http://localhost:3000/gogits/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" - test(tmp, "gogits/src@190d949293", TestRepoURL) + assert(tmp, "gogits/src@190d949293", TestRepoURL) tmp = "http://localhost:3000/gogits/src/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" - test(tmp, "gogits/src@190d949293", TestRepoURL) + assert(tmp, "gogits/src@190d949293", TestRepoURL) // but if there is a sub path, we cannot reliably distinguish the repo name from the app route tmp = "http://localhost:3000/sub/gogits/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" - test(tmp, "sub/gogits@190d949293", TestRepoURL) + assert(tmp, "sub/gogits@190d949293", TestRepoURL) }) t.Run("Compare", func(t *testing.T) { tmp := util.URLJoin(TestRepoURL, "compare", "d8a994ef243349f321568f9e36d5c3f444b99cae..190d9492934af498c3f669d6a2431dc5459e5b20") - test(tmp, "d8a994ef24..190d949293", TestRepoURL) - test(tmp, ""+TestOrgRepo+"@d8a994ef24..190d949293", "https://localhost/forgejo/forgejo") + assert(tmp, "d8a994ef24..190d949293", TestRepoURL) + assert(tmp, ""+TestOrgRepo+"@d8a994ef24..190d949293", "https://localhost/forgejo/forgejo") + defer test.MockVariableValue(&setting.AppURL, TestAppURL+"sub/")() tmp = "http://localhost:3000/sub/gogits/gogs/compare/190d9492934af498c3f669d6a2431dc5459e5b20..d8a994ef243349f321568f9e36d5c3f444b99cae" - test(tmp, "190d949293..d8a994ef24", "http://localhost:3000/sub/gogits/gogs") - test(tmp, "gogits/gogs@190d949293..d8a994ef24", "http://localhost:3000/gogits/gogs") - test(tmp, "gogits/gogs@190d949293..d8a994ef24", "https://external-link.gitea.io/go-gitea/gitea") + assert(tmp, "190d949293..d8a994ef24", "http://localhost:3000/sub/gogits/gogs") + assert(tmp, "gogits/gogs@190d949293..d8a994ef24", "http://localhost:3000/sub/gogits/gugs") + defer test.MockVariableValue(&setting.AppURL, "https://external-link.gitea.io/")() + assert(tmp, "localhost:3000/sub/gogits/gogs@190d949293..d8a994ef24", "https://external-link.gitea.io/go-gitea/gitea") + defer test.MockVariableValue(&setting.AppURL, TestAppURL+"sub1/sub2/sub3/")() tmp = "http://localhost:3000/sub1/sub2/sub3/gogits/gogs/compare/190d9492934af498c3f669d6a2431dc5459e5b20..d8a994ef243349f321568f9e36d5c3f444b99cae" - test(tmp, "190d949293..d8a994ef24", "http://localhost:3000/sub1/sub2/sub3/gogits/gogs") - test(tmp, "gogits/gogs@190d949293..d8a994ef24", "http://localhost:3000/sub1/gogits/gogs") - test(tmp, "gogits/gogs@190d949293..d8a994ef24", "https://external-link.gitea.io/go-gitea/gitea") + assert(tmp, "190d949293..d8a994ef24", "http://localhost:3000/sub1/sub2/sub3/gogits/gogs") + assert(tmp, "gogits/gogs@190d949293..d8a994ef24", "/gogits/gous") + assert(tmp, "gogits/gogs@190d949293..d8a994ef24", "https://external-link.gitea.io/go-gitea/gitea") tmp = "https://codeberg.org/forgejo/forgejo/compare/8bbac4c679bea930c74849c355a60ed3c52f8eb5...e2278e5a38187a1dc84dc41d583ec8b44e7257c1?files=options/locale/locale_fi-FI.ini" - test(tmp, "8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini)", "https://codeberg.org/forgejo/forgejo") - test(tmp, "forgejo/forgejo@8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini)", TestRepoURL) - test(tmp+".", "forgejo/forgejo@8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini).", TestRepoURL) + assert(tmp, "codeberg.org/forgejo/forgejo@8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini)", TestRepoURL) + assert(tmp+".", "codeberg.org/forgejo/forgejo@8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini).", TestRepoURL) + defer test.MockVariableValue(&setting.AppURL, "https://codeberg.org/")() + assert(tmp, "8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini)", "https://codeberg.org/forgejo/forgejo") tmp = "https://codeberg.org/forgejo/forgejo/compare/8bbac4c679bea930c74849c355a60ed3c52f8eb5...e2278e5a38187a1dc84dc41d583ec8b44e7257c1?files=options/locale/locale_fi-FI.ini#L2" - test(tmp, "8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini#L2)", "https://codeberg.org/forgejo/forgejo") + assert(tmp, "8bbac4c679...e2278e5a38 (options/locale/locale_fi-FI.ini#L2)", "https://codeberg.org/forgejo/forgejo") }) t.Run("Invalid URLs", func(t *testing.T) { tmp := "https://local host/gogits/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20" - test(tmp, "https://local host/gogits/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20", TestRepoURL) + assert(tmp, "https://local host/gogits/src/commit/190d9492934af498c3f669d6a2431dc5459e5b20", TestRepoURL) }) } func TestRender_IssueIndexPatternRef(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() test := func(input, expected string) { var buf strings.Builder @@ -428,7 +439,7 @@ func TestRender_IssueIndexPatternRef(t *testing.T) { } func TestRender_FullIssueURLs(t *testing.T) { - setting.AppURL = TestAppURL + defer test.MockVariableValue(&setting.AppURL, TestAppURL)() test := func(input, expected string) { var result strings.Builder diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index c7c53e2678..8305ada25e 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -41,7 +41,7 @@ func TestMain(m *testing.M) { } func TestRender_Commits(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() test := func(input, expected string) { buffer, err := markup.RenderString(&markup.RenderContext{ Ctx: git.DefaultContext, @@ -94,10 +94,19 @@ func TestRender_Commits(t *testing.T) { fileStrangeChars := util.URLJoin(repo, "src", "commit", "eeb243c3395e1921c5d90e73bd739827251fc99d", "path", "to", "file%20%23.txt") test(fileStrangeChars, `

eeb243c339/path/to/file #.txt

`) + + commitLink := util.URLJoin(repo, "src", "commit", "eeb243c3395e1921c5d90e73bd739827251fc99d") + test(commitLink, `

eeb243c339

`) + + crossCommitLink := util.URLJoin(markup.TestAppURL, "forgejo/forgejo", "src", "commit", "eeb243c3395e1921c5d90e73bd739827251fc99d") + test(crossCommitLink, `

forgejo/forgejo@eeb243c339

`) + + extCommitLink := util.URLJoin("https://codeberg.org/", markup.TestOrgRepo, "src", "commit", "eeb243c3395e1921c5d90e73bd739827251fc99d") + test(extCommitLink, `

codeberg.org/`+markup.TestOrgRepo+`@eeb243c339

`) } func TestRender_CrossReferences(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() test := func(input, expected string) { buffer, err := markup.RenderString(&markup.RenderContext{ @@ -140,7 +149,7 @@ func TestRender_CrossReferences(t *testing.T) { } func TestRender_links(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() test := func(input, expected string) { buffer, err := markup.RenderString(&markup.RenderContext{ @@ -242,12 +251,12 @@ func TestRender_links(t *testing.T) { } func TestRender_PullReviewCommitLink(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() sha := "190d9492934af498c3f669d6a2431dc5459e5b20" prCommitLink := util.URLJoin(markup.TestRepoURL, "pulls", "1", "commits", sha) - test := func(input, expected, base string) { + assert := func(input, expected, base string) { buffer, err := markup.RenderString(&markup.RenderContext{ Ctx: git.DefaultContext, RelativePath: ".md", @@ -261,27 +270,28 @@ func TestRender_PullReviewCommitLink(t *testing.T) { assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) } - test(prCommitLink, `

!1 (commit `+sha[0:10]+`)

`, markup.TestRepoURL) + assert(prCommitLink, `

!1 (commit `+sha[0:10]+`)

`, markup.TestRepoURL) prCommitLink = util.URLJoin(markup.TestAppURL, "sub1", "sub2", markup.TestOrgRepo, "pulls", "1", "commits", sha) - test( + assert( prCommitLink, - `

!1 (commit `+sha[0:10]+`)

`, + `

localhost:3000/sub1/sub2/gogits/gogs@!1 (commit `+sha[0:10]+`)

`, util.URLJoin(markup.TestAppURL, "sub1", "sub2", markup.TestOrgRepo), ) - test( + assert( prCommitLink, - `

`+markup.TestOrgRepo+`@!1 (commit `+sha[0:10]+`)

`, + `

localhost:3000/sub1/sub2/gogits/gogs@!1 (commit `+sha[0:10]+`)

`, markup.TestRepoURL, ) prCommitLink = "https://codeberg.org/forgejo/forgejo/pulls/7979/commits/4d968c08e0a8d24bd2f3fb2a3a48b37e6d84a327#diff-7649acfa98a9ee3faf0d28b488bbff428317fc72" - test(prCommitLink, `

!7979 (commit 4d968c08e0)

`, "https://codeberg.org/forgejo/forgejo") - test(prCommitLink, `

forgejo/forgejo@!7979 (commit 4d968c08e0)

`, markup.TestRepoURL) + assert(prCommitLink, `

codeberg.org/forgejo/forgejo@!7979 (commit 4d968c08e0)

`, markup.TestRepoURL) + defer test.MockVariableValue(&setting.AppURL, "https://codeberg.org/")() + assert(prCommitLink, `

!7979 (commit 4d968c08e0)

`, "https://codeberg.org/forgejo/forgejo") } func TestRender_email(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() test := func(input, expected string) { res, err := markup.RenderString(&markup.RenderContext{ @@ -365,7 +375,7 @@ func TestRender_email(t *testing.T) { } func TestRender_emoji(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() setting.StaticURLPrefix = markup.TestAppURL test := func(input, expected string) { @@ -432,7 +442,7 @@ func TestRender_emoji(t *testing.T) { } func TestRender_ShortLinks(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() tree := util.URLJoin(markup.TestRepoURL, "src", "master") test := func(input, expected, expectedWiki string) { @@ -545,7 +555,7 @@ func TestRender_ShortLinks(t *testing.T) { } func TestRender_RelativeImages(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() test := func(input, expected, expectedWiki string) { buffer, err := markdown.RenderString(&markup.RenderContext{ @@ -585,7 +595,7 @@ func TestRender_RelativeImages(t *testing.T) { } func Test_ParseClusterFuzz(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() localMetas := map[string]string{ "user": "go-gitea", @@ -621,7 +631,7 @@ func Test_ParseClusterFuzz(t *testing.T) { } func TestPostProcess_RenderDocument(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() setting.StaticURLPrefix = markup.TestAppURL // can't run standalone localMetas := map[string]string{ @@ -666,7 +676,7 @@ func TestPostProcess_RenderDocument(t *testing.T) { } func TestIssue16020(t *testing.T) { - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() localMetas := map[string]string{ "user": "go-gitea", @@ -731,7 +741,7 @@ func TestIssue18471(t *testing.T) { }, strings.NewReader(data), &res) require.NoError(t, err) - assert.Equal(t, "783b039...da951ce", res.String()) + assert.Equal(t, "domain/org/repo@783b039...da951ce", res.String()) } func TestRender_FilePreview(t *testing.T) { @@ -740,7 +750,7 @@ func TestRender_FilePreview(t *testing.T) { defer test.MockVariableValue(&setting.Langs, []string{"en-US"})() translation.InitLocales(t.Context()) - setting.AppURL = markup.TestAppURL + defer test.MockVariableValue(&setting.AppURL, markup.TestAppURL)() markup.Init(&markup.ProcessorHelper{ GetRepoFileBlob: func(ctx context.Context, ownerName, repoName, commitSha, filePath string, language *string) (*git.Blob, error) { gitRepo, err := git.OpenRepository(git.DefaultContext, "./tests/repo/repo1_filepreview") @@ -880,7 +890,7 @@ func TestRender_FilePreview(t *testing.T) { testRender( urlWithSub, - `

gogits/gogs@190d949293/path/to/file.go (L2-L3)

`, + `

localhost:3000/sub/gogits/gogs@190d949293/path/to/file.go (L2-L3)

`, localMetas, ) @@ -920,7 +930,7 @@ func TestRender_FilePreview(t *testing.T) { testRender( "first without sub "+commitFilePreview+" second "+urlWithSub, - `

first without sub 190d949293/path/to/file.go (L2-L3) second

`+ + `

first without sub localhost:3000/gogits/gogs@190d949293/path/to/file.go (L2-L3) second

`+ `
`+ `
`+ `
`+ diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index 8a3da3b08f..1ea3375ab5 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -1,4 +1,5 @@ // Copyright 2019 The Gitea Authors. All rights reserved. +// Copyright 2025 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package markdown @@ -87,6 +88,8 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa if scope, found := ctx.Metas["scope"]; found { v.Name = fmt.Appendf(v.Name, "-%s", scope) } + case *ast.RawHTML: + g.transformRawHTML(ctx, v, reader) } return ast.WalkContinue, nil }) diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index 7c13494a67..82c2c7fe8c 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -1,4 +1,5 @@ // Copyright 2017 The Gitea Authors. All rights reserved. +// Copyright 2025 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package markdown_test @@ -125,6 +126,32 @@ func TestRender_Images(t *testing.T) { `

`+title+`

`) } +func TestRender_Buttons(t *testing.T) { + setting.AppURL = AppURL + + test := func(input, expected string) { + buffer, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + }, + }, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) + } + + test( + "", + `

`) + + test( + ``, + `

`) + test( + ``, + `

`) +} + func testAnswers(baseURLContent, baseURLImages string) []string { return []string{ `

Wiki! Enjoy :)

diff --git a/modules/markup/markdown/transform_html.go b/modules/markup/markdown/transform_html.go new file mode 100644 index 0000000000..9bebb45554 --- /dev/null +++ b/modules/markup/markdown/transform_html.go @@ -0,0 +1,28 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later + +package markdown + +import ( + "strings" + + "forgejo.org/modules/markup" + + "github.com/yuin/goldmark/ast" + "github.com/yuin/goldmark/text" +) + +func (g *ASTTransformer) addTypeToButton(v *ast.RawHTML, segment string) { + segment = strings.TrimPrefix(segment, " 0 { policy.AllowURLSchemes(setting.Markdown.CustomURLSchemes...) diff --git a/modules/migration/release.go b/modules/migration/release.go index f92cf25e7b..1d9f32ad3c 100644 --- a/modules/migration/release.go +++ b/modules/migration/release.go @@ -10,9 +10,9 @@ import ( // ReleaseAsset represents a release asset type ReleaseAsset struct { - ID int64 - Name string - ContentType *string `yaml:"content_type"` + ID int64 + Name string + Size *int DownloadCount *int `yaml:"download_count"` Created time.Time diff --git a/modules/repository/main_test.go b/modules/repository/main_test.go index 5906b10865..942a805638 100644 --- a/modules/repository/main_test.go +++ b/modules/repository/main_test.go @@ -7,9 +7,6 @@ import ( "testing" "forgejo.org/models/unittest" - - _ "forgejo.org/models/actions" - _ "forgejo.org/models/forgefed" ) func TestMain(m *testing.M) { diff --git a/modules/setting/database.go b/modules/setting/database.go index 91b3c90747..5b8fdaa34c 100644 --- a/modules/setting/database.go +++ b/modules/setting/database.go @@ -86,8 +86,8 @@ func loadDBSetting(rootCfg ConfigProvider) { Database.CharsetCollation = sec.Key("CHARSET_COLLATION").String() Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "forgejo.db")) - Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500) - Database.SQLiteJournalMode = sec.Key("SQLITE_JOURNAL_MODE").MustString("") + Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(60000) + Database.SQLiteJournalMode = sec.Key("SQLITE_JOURNAL_MODE").MustString("WAL") Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(2) if Database.Type.IsMySQL() { @@ -239,12 +239,19 @@ func dbConnStrWithHost(host string) (string, error) { if err := os.MkdirAll(filepath.Dir(Database.Path), os.ModePerm); err != nil { return "", fmt.Errorf("failed to create directories: %w", err) } - journalMode := "" + opts := "" if Database.SQLiteJournalMode != "" { - journalMode = "&_journal_mode=" + Database.SQLiteJournalMode + opts = "&_journal_mode=" + Database.SQLiteJournalMode } - connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d&_txlock=immediate%s", - Database.Path, Database.Timeout, journalMode) + + // in memory mode needs shared cache to be usable by multiple connections + // only used in tests normally + if Database.Path == ":memory:" { + opts += "&cache=shared" + } else { + opts += "&mode=rwc" + } + connStr = fmt.Sprintf("file:%s?_busy_timeout=%d&_txlock=immediate%s", Database.Path, Database.Timeout, opts) default: return "", fmt.Errorf("unknown database type: %s", Database.Type) } diff --git a/modules/ssh/init.go b/modules/ssh/init.go index 432cda0c13..ebc17de69c 100644 --- a/modules/ssh/init.go +++ b/modules/ssh/init.go @@ -85,7 +85,9 @@ func Init(ctx context.Context) error { detailConcat := strings.Join(unexpectedKeys, "\n\t") log.Fatal("An unexpected ssh public key was discovered. Forgejo will shutdown to require this to be fixed. Fix by either:\n"+ "Option 1: Delete the file %s, and Forgejo will recreate it with only expected ssh public keys.\n"+ - "Option 2: Permit unexpected keys by setting [server].SSH_ALLOW_UNEXPECTED_AUTHORIZED_KEYS=true in Forgejo's config file.\n\t"+ + "Option 2: Permit unexpected keys by setting [server].SSH_ALLOW_UNEXPECTED_AUTHORIZED_KEYS=true in Forgejo's config file.\n"+ + "Option 3: If unused, disable SSH support by setting [server].DISABLE_SSH=true in Forgejo's config file.\n"+ + "\t"+ detailConcat, filepath.Join(setting.SSH.RootPath, "authorized_keys")) } } diff --git a/modules/structs/repo_actions.go b/modules/structs/repo_actions.go index eada2db09f..b13f344738 100644 --- a/modules/structs/repo_actions.go +++ b/modules/structs/repo_actions.go @@ -32,27 +32,3 @@ type ActionTaskResponse struct { Entries []*ActionTask `json:"workflow_runs"` TotalCount int64 `json:"total_count"` } - -// ActionRunnerLabel represents a Runner Label -type ActionRunnerLabel struct { - ID int64 `json:"id"` - Name string `json:"name"` - Type string `json:"type"` -} - -// ActionRunner represents a Runner -type ActionRunner struct { - ID int64 `json:"id"` - Name string `json:"name"` - Status string `json:"status"` - Busy bool `json:"busy"` - // currently unused as forgejo does not support ephemeral runners, but they are defined in gh api spec - Ephemeral bool `json:"ephemeral"` - Labels []*ActionRunnerLabel `json:"labels"` -} - -// ActionRunnersResponse returns Runners -type ActionRunnersResponse struct { - Entries []*ActionRunner `json:"runners"` - TotalCount int64 `json:"total_count"` -} diff --git a/modules/templates/main_test.go b/modules/templates/main_test.go index 946bc603f6..422bc497d8 100644 --- a/modules/templates/main_test.go +++ b/modules/templates/main_test.go @@ -9,10 +9,6 @@ import ( "forgejo.org/models/unittest" "forgejo.org/modules/markup" - - _ "forgejo.org/models" - _ "forgejo.org/models/forgefed" - _ "forgejo.org/models/issues" ) func TestMain(m *testing.M) { diff --git a/modules/testimport/import.go b/modules/testimport/import.go new file mode 100644 index 0000000000..cefa5b32a2 --- /dev/null +++ b/modules/testimport/import.go @@ -0,0 +1,17 @@ +// Copyright 2026 The Forgejo Authors +// SPDX-License-Identifier: MIT + +package testimport + +// ensure the init() function of those modules are called in a test +// environment that may not include them. It matters when the engine +// is trying to figure out the ordering of foreign keys, for instance + +import ( //revive:disable:blank-imports + _ "forgejo.org/models/actions" + _ "forgejo.org/models/activities" + _ "forgejo.org/models/auth" + _ "forgejo.org/models/forgefed" + _ "forgejo.org/models/perm/access" + _ "forgejo.org/models/repo" +) diff --git a/modules/translation/translation.go b/modules/translation/translation.go index 42441115af..17c7cc068b 100644 --- a/modules/translation/translation.go +++ b/modules/translation/translation.go @@ -6,7 +6,6 @@ package translation import ( "context" "html/template" - "iter" "sort" "strings" "sync" @@ -328,16 +327,6 @@ func (l *locale) PrettyNumber(v any) string { return l.msgPrinter.Sprintf("%v", number.Decimal(v)) } -func (l *locale) IterWithTr(kvs ...string) iter.Seq2[string, template.HTML] { - return func(yield func(string, template.HTML) bool) { - for i := 0; i < len(kvs); i += 2 { - if !yield(kvs[i], l.TrHTML(kvs[i+1])) { - return - } - } - } -} - func GetPluralRule(l Locale) int { return GetPluralRuleImpl(l.Language()) } diff --git a/options/locale/locale_ar.ini b/options/locale/locale_ar.ini index 256692c080..3130600db6 100644 --- a/options/locale/locale_ar.ini +++ b/options/locale/locale_ar.ini @@ -620,6 +620,8 @@ quota.rule.exceeded = تم تجاوزه quota.applies_to_user = تنطبق قواعد الحصص التالية على حسابك quota.sizes.wiki = الموسوعة +ssh_token_help_ssh_agent = أو، إذا كنت تستخدم وكيل SSH (مع تعيين متغير SSH_AUTH_SOCK): + [org] follow_blocked_user = لا يمكنك إتباع هذه المنظمة لأن هذه المنظمة حظرتك. settings.delete_prompt = ستزال المنظمة إلى الأبد. لا يمكن التراجع عنها بعد ذلك! @@ -1612,6 +1614,19 @@ file.title = %s عند %s vendored = مضمن file_follow = متابعة الروابط الرمزية +unescape_control_characters = الهروب +blame = لوم +editor.file_is_a_symlink = `"%s" هو رابط رمزي. لا يمكن تعديل الروابط الرمزية في محرر الويب.` +editor.file_editing_no_longer_exists = الملف الذي يتم تعديله، "%s"، لم يعد موجودًا في هذا المستودع. +editor.file_deleting_no_longer_exists = الملف الذي يتم تعديله، "%s"، ليس موجودًا في هذا المستودع. +editor.file_changed_while_editing = لقد تغيرت محتويات الملف منذ فتحه. انقر هنا لعرضها أو حفظ التغييرات مرة أخرى لاستبدالها. +editor.commit_id_not_matching = تم تغيير الملف أثناء قيامك بتحريره. قم بإنشاء فرع جديد ثم قم بدمج التغييرات. +editor.push_out_of_date = ­يبدو أن هذا التوجه قديم الطراز. +editor.upload_file_is_locked = الملف "%s"هو مغلق من قبل %s. +editor.cannot_commit_to_protected_branch = لا يمكن الالتزام بالفرع المحمي "%s". +editor.user_no_push_to_branch = المستخدم لا يمكن الالتزام بالفرع المحمي. +editor.require_signed_commit = يتطلب الفرع التزامًا موقعًا + [mail] admin.new_user.text = من فضلك اضغط هنا لإدارة هذا المستخدم من لوحة الإدارة. admin.new_user.subject = مستخدم جديد: %s سجل حالاً @@ -2117,10 +2132,10 @@ variables.management = إدارة المتغيرات runners.task_list.repository = المستودع variables = المتغيرات variables.deletion.description = إزالة المتغيرات عملية نهائية لا يمكن التراجع عنها. أتريد الاستمرار؟ -status.failure = "فشل" +status.failure = فشل runners.status.idle = خامل runners.task_list.done_at = تم عند -status.running = "يعمل" +status.running = يعمل runners.status.active = نشيط runners.status = الحالة runners.description = الوصف @@ -2128,15 +2143,15 @@ runners.update_runner = حدّث التغييرات runners.name = الاسم runners.version = النسخة runs.status = الحالة -status.unknown = "مجهول" +status.unknown = مجهول runners.owner_type = النوع -status.waiting = "ينتظر" +status.waiting = ينتظر runners.labels = التصنيفات runners.status.unspecified = مجهول runs.commit = إيداع -status.success = "نجح" +status.success = نجح runs.empty_commit_message = (رسالة إيداع فارغة) -status.cancelled = "ملغي" +status.cancelled = ملغي runs.status_no_select = كل الحالات runs.scheduled = مُجدوَل variables.edit = عدّل المتغير @@ -2261,8 +2276,8 @@ default_key = موقّع بالمفتاح المبدئي error.extract_sign = تعذّر استخراج التوقيع error.generate_hash = تعذّر إنشاء بصمة الإيداع error.no_committer_account = لا حساب مرتبط ببريد المودِع -error.not_signed_commit = "ليس إيداعًا موقّعًا" -error.failed_retrieval_gpg_keys = "تعذّر جلب مفتاح مرتبط بحساب المودِع" +error.not_signed_commit = ليس إيداعًا موقّعًا +error.failed_retrieval_gpg_keys = تعذّر جلب مفتاح مرتبط بحساب المودِع [graphs] component_loading = يحمّل %s... diff --git a/options/locale/locale_bg.ini b/options/locale/locale_bg.ini index b8c11a6807..6cf85867bc 100644 --- a/options/locale/locale_bg.ini +++ b/options/locale/locale_bg.ini @@ -138,6 +138,13 @@ webauthn_unsupported_browser = Вашият браузър в момента н webauthn_error_duplicated = Ключът за сигурност не е разрешен за тази заявка. Моля, уверете се, че ключът не е вече регистриран. tracked_time_summary = Обобщение на проследеното време въз основа на филтрите в списъка със задачи +active_stopwatch = Активен тракер за време +access_token = Токен за достъп +passcode = Паскод + +rerun_all = Повторно изпълнение на всички задания +download_logs = Изтегляне на дневниците + [settings] ui = Тема delete_key = Премахване @@ -380,6 +387,89 @@ quota.sizes.all = Всички quota.sizes.repos.all = Хранилища quota.sizes.assets.attachments.issues = Прикачени файлове към задачи +openid_deletion = Премахване на OpenID адрес +openid_deletion_desc = Премахването на този OpenID адрес от вашия акаунт ще ви попречи да влизате с него. Продължаване? +openid_deletion_success = OpenID адресът е премахнат. +add_new_openid = Добавяне на нов OpenID URI +add_openid = Добавяне на OpenID URI +add_openid_success = Новият OpenID адрес е добавен. +openid_desc = OpenID ви позволява да делегирате удостоверяването на външен доставчик. +ssh_desc = Тези публични SSH ключове са свързани с вашия акаунт. Съответните частни ключове позволяват пълен достъп до вашите хранилища. SSH ключове, които са потвърдени, могат да се използват за проверка на SSH-подписани Git подавания. +principal_desc = Тези SSH certificate principals са свързани с вашия акаунт и позволяват пълен достъп до вашите хранилища. +gpg_desc = Тези публични GPG ключове са свързани с вашия акаунт и се използват за потвърждаване на вашите подавания. Пазете частните си ключове в безопасност, тъй като те позволяват подписване на подавания с вашата самоличност. +add_new_principal = Добавяне на principal +ssh_principal_been_used = Този principal вече е добавен към сървъра. +gpg_no_key_email_found = Този GPG ключ не съвпада с нито един активиран адрес за ел. поща, свързан с вашия акаунт. Той все пак може да бъде добавен, ако подпишете предоставения токен. +gpg_key_matched_identities = Съвпадащи самоличности: +gpg_key_matched_identities_long = Вградените самоличности в този ключ съвпадат със следните активирани адреси за ел. поща на този потребител. Подавания, които съвпадат с тези адреси, могат да бъдат проверени с този ключ. +gpg_key_verified = Потвърден ключ +gpg_key_verified_long = Ключът е потвърден с токен и може да се използва за проверка на подавания, които съвпадат с активирани адреси за ел. поща на този потребител, в допълнение към всички съвпадащи самоличности за този ключ. +gpg_key_verify = Потвърждаване +gpg_invalid_token_signature = Предоставените GPG ключ, подпис и токен не съвпадат или токенът е изтекъл. +gpg_token_required = Трябва да предоставите подпис за токена по-долу +gpg_token = Токен +gpg_token_help = Можете да генерирате подпис чрез: +gpg_token_signature = Брониран (Armored) GPG подпис +verify_gpg_key_success = GPG ключът „%s“ е потвърден. +ssh_key_verified = Потвърден ключ +ssh_key_verified_long = Ключът е потвърден с токен и може да се използва за проверка на подавания, които съвпадат с активирани адреси за ел. поща на този потребител. +ssh_key_verify = Потвърждаване +ssh_invalid_token_signature = Предоставените SSH ключ, подпис или токен не съвпадат, или токенът е изтекъл. +ssh_token_required = Трябва да предоставите подпис за токена по-долу +ssh_token = Токен +ssh_token_help = Можете да генерирате подпис чрез: +ssh_token_help_ssh_agent = или ако използвате SSH агент (със зададена променлива SSH_AUTH_SOCK): +ssh_token_signature = Брониран (Armored) SSH подпис +verify_ssh_key_success = SSH ключът „%s“ е потвърден. +subkeys = Подключове +add_principal_success = SSH certificate principal „%s“ е добавен. +ssh_principal_deletion = Премахване на SSH Certificate Principal +ssh_key_deletion_desc = Премахването на SSH ключ отнема достъпа му до вашия акаунт. Продължаване? +gpg_key_deletion_desc = Премахването на GPG ключ премахва потвърждението на подаванията, подписани от него. Продължаване? +ssh_principal_deletion_desc = Премахването на SSH Certificate Principal отнема достъпа му до вашия акаунт. Продължаване? +ssh_principal_deletion_success = Този principal е премахнат. +token_state_desc = Този токен е използван през последните 7 дни +principal_state_desc = Този principal е използван през последните 7 дни +ssh_signonly = В момента SSH е изключен, затова тези ключове се използват само за проверка на подписи на подавания. +manage_access_token = Токени за достъп +generate_new_token = Генериране на нов токен +tokens_desc = Тези токени дават достъп до вашия акаунт чрез Forgejo API. +token_name = Име на токена +generate_token = Генериране на токен +generate_token_success = Новият ви токен е генериран. Копирайте го сега, тъй като няма да бъде показан отново. +access_token_deletion = Изтриване на токен за достъп +access_token_deletion_desc = Изтриването на токен ще отнеме достъпа до вашия акаунт за приложенията, които го използват. Това не може да бъде отменено. Продължаване? +delete_token_success = Токенът е изтрит. Приложенията, които го използват, вече нямат достъп до вашия акаунт. +regenerate_token = Повторно генериране +access_token_regeneration = Повторно генериране на токен за достъп +access_token_regeneration_desc = Повторното генериране на токен ще отнеме достъпа до вашия акаунт за приложенията, които го използват. Това не може да бъде отменено. Продължаване? +regenerate_token_success = Токенът е генериран повторно. Приложенията, които го използват, вече нямат достъп до вашия акаунт и трябва да бъдат обновени с новия токен. +select_permissions = Избор на разрешения +access_token_desc = Избраните разрешения на токена ограничават упълномощаването само до съответните API маршрути. Прочетете документацията за повече информация. +at_least_one_permission = Трябва да изберете поне едно разрешение, за да създадете токен +oauth2_confidential_client = Поверителен клиент. Изберете за приложения, които пазят тайната поверителна, като например уеб приложения. Не избирайте за нейтив приложения (настолни и мобилни). +oauth2_redirect_uris = URI за пренасочване. Моля, използвайте нов ред за всеки URI. +oauth2_client_id = ID на клиента +oauth2_client_secret = Тайна на клиента +oauth2_regenerate_secret = Повторно генериране на тайна +oauth2_regenerate_secret_hint = Загубили сте тайната си? +oauth2_application_create_description = OAuth2 приложенията дават достъп на вашето външно приложение до потребителски акаунти в тази инстанция. +oauth2_application_remove_description = Премахването на OAuth2 приложение ще му попречи да осъществява достъп до упълномощени потребителски акаунти в тази инстанция. Продължаване? +oauth2_application_locked = Forgejo предварително регистрира някои OAuth2 приложения при стартиране, ако е включено в конфигурацията. За да се предотврати неочаквано поведение, те не могат да бъдат нито редактирани, нито премахнати. Моля, вижте документацията на OAuth2 за повече информация. +authorized_oauth2_applications_description = Предоставили сте достъп до личния си акаунт във Forgejo на тези външни приложения. Моля, отнемете достъпа за приложения, които вече не използвате. +twofa_scratch_token_regenerate = Повторно генериране на ключ за еднократно възстановяване +twofa_scratch_token_regenerated = Вашият ключ за еднократно възстановяване вече е %s. Съхранете го на сигурно място, тъй като няма да бъде показан отново. +or_enter_secret = Или въведете тайната: %s +then_enter_passcode = И въведете паскода, показан в приложението: +passcode_invalid = Паскодът е неправилен. Опитайте отново. +twofa_enrolled = Вашият акаунт беше успешно включен. Съхранете ключа си за еднократно възстановяване (%s) на сигурно място, тъй като няма да бъде показан отново. +twofa_failed_get_secret = Неуспешно получаване на тайната. +webauthn_desc = Ключовете за сигурност са хардуерни устройства, съдържащи криптографски ключове. Те могат да се използват за двуфакторно удостоверяване. Ключовете за сигурност трябва да поддържат стандарта WebAuthn Authenticator. +manage_account_links_desc = Тези външни акаунти са свързани към вашия акаунт във Forgejo. +remove_account_link_desc = Премахването на свързан акаунт ще отнеме достъпа му до вашия акаунт във Forgejo. Продължаване? +remove_account_link_success = Свързаният акаунт е премахнат. +delete_with_all_comments = Вашият акаунт е създаден преди по-малко от %s. За да се избегнат коментари-призраци, всички коментари към задачи/заявки за сливане ще бъдат изтрити заедно с него. + [packages] container.labels.value = Стойност alpine.repository.repositories = Хранилища @@ -829,7 +919,7 @@ settings.danger_zone = Опасна зона issues.closed_by = от %[3]s бе затворена %[1]s issues.delete_comment_confirm = Сигурни ли сте, че искате да изтриете този коментар? milestones.due_date = Краен срок (опционално) -settings.wiki_delete_notices_1 = - Това ще изтрие перманентно и ще деактивира уикито на хранилището %s. +settings.wiki_delete_notices_1 = - Това ще изтрие перманентно и ще изключи уикито на хранилището %s. settings.wiki_deletion_success = Данните на уикито на хранилището са изтрити. settings.collaborator_deletion = Премахване на сътрудника settings.remove_collaborator_success = Сътрудникът е премахнат. @@ -1211,7 +1301,7 @@ diff.file_byte_size = Размер branch.create_success = Клонът „%s“ е създаден. branch.deletion_success = Клонът „%s“ е изтрит. branch.deletion_failed = Неуспешно изтриване на клона „%s“. -branch.rename_branch_to = Преименуване от „%s“ на: +branch.rename_branch_to = Преименуване на клона „%s“. settings.web_hook_name_msteams = Microsoft Teams settings.web_hook_name_dingtalk = DingTalk branch.renamed = Клонът %s е преименуван на %s. @@ -1350,7 +1440,7 @@ issues.review.resolve_conversation = Решаване на обсъжданет diff.comment.markdown_info = Поддържа се стилизиране с Маркдаун. diff.file_suppressed = Разликите във файла са потиснати, защото са твърде много pulls.reject_count_n = %d поискани промени -settings.pulls.default_allow_edits_from_maintainers = Позволяване на редакции от поддържащите по подразбиране +settings.pulls.default_allow_edits_from_maintainers = Позволяване по подразбиране на редакции от поддържащите fork_branch = Клон за клониране в разклонението issues.review.resolved_by = отбеляза това обсъждане като решено issues.role.member = Участник @@ -1480,7 +1570,7 @@ new_advanced = Разширени настройки new_from_template = Използване на шаблон new_from_template_description = Можете да изберете съществуващо шаблонно хранилище в тази инстанция и да приложите неговите настройки. settings.event_pull_request_comment = Коментари -repo_gitignore_helper_desc = Изберете кои файлове да не се проследяват от списък с шаблони за обичайните езици. Типичните артефакти, генерирани от инструментите за изграждане, са включени в .gitignore по подразбиране. +repo_gitignore_helper_desc = Изберете кои файлове да не се проследяват от списък с шаблони за обичайните езици. Типичните артефакти, генерирани от инструментите за изграждане, са включени по подразбиране в .gitignore. object_format_helper = Формат на обектите на хранилището. Не може да се променя по-късно. SHA1 е най-съвместим. issues.num_reviews_one = %d рецензия settings.event_pull_request = Изменение @@ -1654,7 +1744,7 @@ commits.signed_by_untrusted_user = Подписано от недоверен п commits.signed_by_untrusted_user_unmatched = Подписано от недоверен потребител, който не съвпада с подаващия issues.lock.notice_1 = - Други потребители не могат да добавят нови коментари към тази задача. issues.unlock.notice_2 = - Винаги можете да заключите тази задача отново в бъдеще. -issues.unlock.title = Отключване на обсъждането по тази задача. +issues.unlock.title = Отключване на обсъждането issues.dependency.no_permission_1 = Нямате разрешение да прочетете %d зависимост issues.reopen.blocked_by_user = Не можете да отворите наново тази задача, защото сте блокирани от притежателя на хранилището или от автора на тази задача. compare.compare_base = основа @@ -1736,7 +1826,7 @@ mirror_address_url_invalid = Предоставеният URL е невалид template.git_content = Git съдържание (стандартен клон) ambiguous_runes_description = `Този файл съдържа Уникод знаци, които могат да бъдат объркани с други знаци. Ако смятате, че това е умишлено, можете спокойно да пренебрегнете това предупреждение. Използвайте бутона „Екраниране“, за да ги разкриете.` issues.lock.notice_3 = - Винаги можете да отключите тази задача отново в бъдеще. -issues.lock.title = Заключване на обсъждането по тази задача. +issues.lock.title = Заключване на обсъждането issues.dependency.issue_batch_close_blocked = Не могат да бъдат затворени групово избраните задачи, защото задача #%d все още има отворени зависимости issues.dependency.add_error_cannot_create_circular = Не можете да създадете зависимост с две задачи, които се блокират взаимно. issues.review.add_review_requests = поиска рецензии от %[1]s %[2]s @@ -1810,6 +1900,97 @@ release.summary_card_alt = Карта с обобщение на издание release.asset_external_url = Външен URL адрес error.csv.too_large = Не може да се визуализира този файл, защото е твърде голям. +commit.cherry-pick = Отбиране +pulls.cmd_instruction_checkout_title = Изтегляне +pulls.cmd_instruction_merge_title = Сливане +settings.branches.switch_default_branch = Превключване на стандартния клон +settings.branches.add_new_rule = Добавяне на ново правило +settings.pulls.ignore_whitespace = Игнориране на празните знаци при конфликти +settings.pulls.enable_autodetect_manual_merge = Включване на автоматично откриване на ръчно сливане (Бележка: В някои специални случаи може да възникнат грешни преценки) +settings.pulls.allow_rebase_update = Включване на обновяването на клон на заявка за сливане чрез пребазиране +settings.pulls.default_delete_branch_after_merge = Изтриване по подразбиране на клона на заявката за сливане след сливане +settings.admin_code_indexer = Индексатор на код +settings.admin_stats_indexer = Индексатор на статистика на кода +settings.admin_indexer_commit_sha = Последно индексирано подаване +settings.admin_indexer_unindexed = Неиндексирано +settings.reindex_button = Добавяне към опашката за преиндексиране +settings.reindex_requested = Поискано преиндексиране +settings.admin_enable_close_issues_via_commit_in_any_branch = Затваряне на задача чрез подаване, направено в клон, различен от стандартния +settings.new_owner_has_same_repo = Новият притежател вече има хранилище със същото име. Моля, изберете друго име. +settings.new_owner_blocked_doer = Новият притежател ви е блокирал. +settings.convert = Преобразуване в обикновено хранилище +settings.convert_fork = Преобразуване в обикновено хранилище +settings.convert_fork_confirm = Преобразуване на хранилището +settings.transfer.rejected = Прехвърлянето на хранилището е отхвърлено. +settings.transfer.success = Прехвърлянето на хранилището е успешно. +settings.transfer_abort = Отказ от прехвърлянето +settings.transfer_abort_invalid = Не можете да отмените несъществуващо прехвърляне на хранилище. +settings.transfer_abort_success = Прехвърлянето на хранилището към %s е успешно отменено. +settings.transfer_in_progress = В момента има текущо прехвърляне. Моля, отменете го, ако искате да прехвърлите това хранилище на друг потребител. +settings.transfer_notices_1 = - Ще загубите достъп до хранилището, ако го прехвърлите на индивидуален потребител. +settings.transfer_notices_2 = - Ще запазите достъп до хранилището, ако го прехвърлите на организация, която (съ)притежавате. +settings.transfer_notices_3 = - Ако хранилището е частно и се прехвърля на индивидуален потребител, това действие гарантира, че потребителят има поне разрешение за четене (и променя разрешенията, ако е необходимо). +settings.transfer_perform = Извършване на прехвърлянето +settings.transfer_started = Това хранилище е отбелязано за прехвърляне и очаква потвърждение от „%s“ +settings.transfer_succeed = Хранилището е прехвърлено. +settings.transfer_quota_exceeded = Новият притежател (%s) е надвишил квотата си. Хранилището не е прехвърлено. +settings.wiki_rename_branch_main = Нормализиране на името на клона на уикито +settings.wiki_rename_branch_main_desc = Преименуване на клона, използван вътрешно от уикито, на „%s“. Тази промяна е перманентна и не може да бъде отменена. +settings.wiki_rename_branch_main_notices_1 = Тази операция НЕ МОЖЕ да бъде отменена. +settings.wiki_branch_rename_success = Името на клона на уикито на хранилището е нормализирано успешно. +settings.wiki_branch_rename_failure = Неуспешно нормализиране на името на клона на уикито на хранилището. +settings.update_settings_no_unit = Хранилището трябва да позволява поне някакъв вид взаимодействие. +settings.change_team_access_not_allowed = Промяната на достъпа на екипа до хранилището е ограничена до притежателя на организацията +settings.team_not_in_organization = Екипът не е в същата организация като хранилището +settings.add_team_success = Екипът вече има достъп до хранилището. +settings.change_team_permission_tip = Разрешението на екипа се задава на страницата с настройки на екипа и не може да се променя за отделно хранилище +settings.delete_team_tip = Този екип има достъп до всички хранилища и не може да бъде премахнат +settings.remove_team_success = Достъпът на екипа до хранилището е премахнат. +settings.add_webhook.invalid_channel_name = Името на канала на уеб-куката не може да бъде празно и не може да съдържа само знак #. +settings.add_webhook.invalid_path = Пътят не трябва да съдържа част, която е „.“ или „..“ или празен низ. Той не може да започва или завършва с наклонена черта. +settings.hooks_desc = Уеб-куките автоматично правят HTTP POST заявки към сървър, когато се задействат определени събития във Forgejo. Прочетете повече в ръководството за уеб-куки. +settings.webhook_deletion = Премахване на уеб-кука +settings.webhook_deletion_desc = Премахването на уеб-кука изтрива нейните настройки и историята на доставките. Продължаване? +settings.webhook_deletion_success = Уеб-куката е премахната. +settings.webhook.test_delivery = Тестване на доставката +settings.webhook.test_delivery_desc = Тествайте тази уеб-кука с фалшиво събитие. +settings.webhook.test_delivery_desc_disabled = За да тествате тази уеб-кука с фалшиво събитие, я активирайте. +settings.webhook.replay.description = Повторно изпълнение на тази уеб-кука. +settings.webhook.replay.description_disabled = За да изпълните повторно тази уеб-кука, я активирайте. +settings.webhook.delivery.success = Събитие е добавено към опашката за доставка. Може да отнеме няколко секунди, преди да се появи в историята на доставките. +settings.githooks_desc = Git куките се задвижват от самия Git. Можете да редактирате файловете с куки по-долу, за да настроите персонализирани операции. +settings.githook_edit_desc = Ако куката е неактивна, ще бъде представено примерно съдържание. Оставянето на съдържанието с празна стойност ще изключи тази кука. +settings.githook_name = Име на куката +settings.githook_content = Съдържание на куката +settings.update_githook = Обновяване на куката +settings.add_webhook_desc = Forgejo ще изпраща POST заявки с определен Content-Type до целевия URL адрес. Прочетете повече в ръководството за уеб-куки. +settings.payload_url = Целеви URL адрес +settings.secret = Тайна +settings.protected_branch.save_rule = Запазване на правилото +settings.protected_branch.delete_rule = Изтриване на правилото +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.require_signed_commits = Изискване на подписани подавания +settings.require_signed_commits_desc = Отхвърляне на изтласквания към този клон, ако те са неподписани или не могат да бъдат потвърдени. +settings.enforce_on_admins = Принудително прилагане на това правило за администраторите на хранилището +settings.enforce_on_admins_desc = Администраторите на хранилището не могат да заобикалят това правило. +settings.merge_style_desc = Стилове на сливане +settings.default_merge_style_desc = Стил на сливане по подразбиране +settings.choose_branch = Изберете клон… +settings.edit_protected_branch = Редактиране +settings.chat_id = ID на чата +settings.thread_id = ID на нишката +settings.matrix.room_id = ID на стаята +settings.matrix.message_type = Тип съобщение + +issues.label_open_issues = %d отворени задачи/заявки за сливане +issues.summary_card_alt = Карта с обобщение на задача със заглавие „%s“ в хранилище %s +release.type_attachment = Прикачен файл + [modal] confirm = Потвърждаване no = Не @@ -1844,6 +2025,8 @@ buttons.indent.tooltip = Вмъкване на елементи с едно ни buttons.unindent.tooltip = Изваждане на елементи с едно ниво link_modal.paste_reminder = Подсказка: С URL адрес в клипборда можете да поставите директно в редактора, за да създадете връзка. +link_modal.url = Адрес + [org] teams.write_access = Писане settings.location = Местоположение @@ -1985,7 +2168,7 @@ docker_helper = Ако стартирате Forgejo в Docker, моля, про sqlite_helper = Път на файла за SQLite3 базата данни.
Въведете абсолютен път, ако стартирате Forgejo като service. err_empty_admin_email = Администраторският адрес за ел. поща не може да бъде празен. password_algorithm = Алгоритъм за хеш. на паролите -default_keep_email_private = Скриване на адресите за ел. поща по подразбиране +default_keep_email_private = Скриване по подразбиране на адресите за ел. поща invalid_password_algorithm = Невалиден алгоритъм за хеш. на паролите err_admin_name_is_reserved = Потребителското име на администратора е невалидно, потребителското име е резервирано err_admin_name_pattern_not_allowed = Потребителското име на администратора е невалидно, потребителското име съответства с резервиран шаблон @@ -2055,6 +2238,18 @@ reset_password.text = Ако това сте вие, моля, щракнете primary_mail_change.subject = Основният ви адрес за ел. поща е променен account_security_caution.text_2 = Ако това не сте били вие, акаунтът ви е компрометиран. Моля, свържете се с администраторите на този сайт. +totp_disabled.subject = TOTP е изключен +totp_disabled.text_1 = Еднократната парола, базирана на време (TOTP), за вашия акаунт току-що беше изключена. +totp_disabled.no_2fa = Вече няма конфигурирани други 2FA методи, което означава, че вече не е необходимо да влизате в акаунта си с 2FA. +removed_security_key.subject = Ключ за сигурност беше премахнат +removed_security_key.text_1 = Ключът за сигурност „%[1]s“ току-що беше премахнат от вашия акаунт. +removed_security_key.no_2fa = Вече няма конфигурирани други 2FA методи, което означава, че вече не е необходимо да влизате в акаунта си с 2FA. +totp_enrolled.subject = Активирахте TOTP като метод за 2FA +totp_enrolled.text_1.no_webauthn = Току-що включихте TOTP за вашия акаунт. Това означава, че за всички бъдещи влизания във вашия акаунт трябва да използвате TOTP като 2FA метод. +totp_enrolled.text_1.has_webauthn = Току-що включихте TOTP за вашия акаунт. Това означава, че за всички бъдещи влизания във вашия акаунт можете да използвате TOTP като 2FA метод или някой от вашите ключове за сигурност. +issue.action.review_dismissed = @%[1]s отхвърли последната рецензия от %[2]s за тази заявка за сливане. +repo.transfer.to_you = вас + [user] joined_on = Присъединени на %s user_bio = Биография @@ -2192,6 +2387,8 @@ config.db_type = Тип monitor.queue.type = Тип notices.type = Тип +users.prohibit_login = Замразен акаунт + [error] not_found = Целта не може да бъде намерена. report_message = Ако смятате, че това е грешка на Forgejo, моля, потърсете в задачите на Codeberg или отворете нова задача, ако е необходимо. @@ -2280,6 +2477,18 @@ invalid_gpg_key = Не може да се потвърди вашият GPG кл git_ref_name_error = ` трябва да е правилно форматирано име на Git препратка.` last_org_owner = Не можете да премахнете последния потребител от екипа на „притежателите“. Трябва да има поне един притежател за организация. +AccessToken = Токен за достъп +CommitChoice = Избор на подаване +username_claiming_cooldown = Потребителското име не може да бъде взето, тъй като периодът му на изчакване все още не е приключил. То може да бъде взето на %[1]s. +repository_force_private = Принудително Частни е включено: частните хранилища не могат да станат публични. +repository_files_already_exist.adopt = Вече съществуват файлове за това хранилище и те могат само да бъдат осиновени. +repository_files_already_exist.adopt_or_delete = Вече съществуват файлове за това хранилище. Или ги осиновете, или ги изтрийте. +visit_rate_limit = Отдалеченото посещение достигна ограничението на честотата. +2fa_auth_required = Отдалеченото посещение изисква двуфакторно удостоверяване. +unset_password = Влезлият потребител не е задал паролата. +unsupported_login_type = Този тип влизане не се поддържа за изтриване на акаунт. +invalid_ssh_principal = Невалиден principal: %s + [action] close_issue = `затвори задача %[3]s#%[2]s` rename_repo = преименува хранилище от %[1]s на %[3]s @@ -2367,6 +2576,28 @@ resend_mail = Щракнете тук, за повторно изпращане change_unconfirmed_email_summary = Промяна на адреса, на който се изпраща ел. писмо за активация. change_unconfirmed_email = Ако сте въвели грешен адрес за ел. поща по време на регистрацията, можете да го промените по-долу и потвърждение ще бъде изпратено на новия адрес. +prohibit_login = Акаунтът е замразен +prohibit_login_desc = Вашият акаунт е замразен и не може да взаимодейства с инстанцията. Свържете се с администратора, за да възстановите достъпа си. +non_local_account = Нелокални потребители не могат да обновяват паролата си чрез уеб интерфейса на Forgejo. +unauthorized_credentials = Идентификационните данни са неправилни или са изтекли. Опитайте отново командата си или вижте %s за повече информация +twofa_passcode_incorrect = Вашият код за достъп (паскод) е неправилен. Ако сте изгубили устройството си, използвайте резервния си код, за да влезете. +oauth_signup_tab = Регистриране на нов акаунт +oauth_signup_title = Завършване на новия акаунт +oauth_signup_submit = Завършване на акаунта +oauth_signin_tab = Свързване към съществуващ акаунт +oauth_signin_title = Влезте, за да упълномощите свързания акаунт +oauth_signin_submit = Свързване на акаунт +oauth.signin.error = Възникна грешка при обработката на заявката за упълномощаване. Ако тази грешка продължава, моля, свържете се с администратора на сайта. +oauth.signin.error.access_denied = Заявката за упълномощаване беше отхвърлена. +oauth.signin.error.temporarily_unavailable = Упълномощаването е неуспешно, защото сървърът за удостоверяване е временно недостъпен. Моля, опитайте отново по-късно. +openid_connect_title = Свързване към съществуващ акаунт +openid_connect_desc = Избраният OpenID URI е неизвестен. Свържете го с нов акаунт тук. +openid_register_desc = Избраният OpenID URI е неизвестен. Свържете го с нов акаунт тук. +disable_forgot_password_mail = Възстановяването на акаунта е изключено, защото няма зададена ел. поща. Моля, свържете се с вашия администратор на сайта. +disable_forgot_password_mail_admin = Възстановяването на акаунта е налично само когато е зададена ел. поща. Моля, задайте ел. поща, за да включите възстановяването на акаунта. +email_domain_blacklisted = Не можете да се регистрирате с вашия адрес за ел. поща. +authorization_failed_desc = Упълномощаването е неуспешно, защото открихме невалидна заявка. Моля, свържете се с поддържащия приложението, което се опитахте да упълномощите. + [aria] footer.software = Относно този софтуер footer.links = Връзки @@ -2503,6 +2734,8 @@ union_tooltip = Включване на резултати, които съвп union = Обединение type_tooltip = Тип търсене +runner_kind = Търсене на изпълнители… + [markup] filepreview.lines = Редове от %[1]d до %[2]d в %[3]s filepreview.line = Ред %[1]d в %[2]s @@ -2548,4 +2781,7 @@ issues.write = Писане: Затваряне на задачи и уп [units] error.no_unit_allowed_repo = Нямате разрешение за достъп до никоя секция на това хранилище. unit = Елемент -error.unit_not_allowed = Нямате разрешение за достъп до тази секция на хранилището. \ No newline at end of file +error.unit_not_allowed = Нямате разрешение за достъп до тази секция на хранилището. + +[secrets] +secrets = Тайни \ No newline at end of file diff --git a/options/locale/locale_bn.ini b/options/locale/locale_bn.ini index 2155f9073c..ebcad77f97 100644 --- a/options/locale/locale_bn.ini +++ b/options/locale/locale_bn.ini @@ -1,8 +1,11 @@ [common] help = সাহায্য dashboard = ড্যাশবোর্ড -home = বাড়ি -explore = দেখোণ +home = হোম +explore = এক্সপ্লোর logo = লোগো -sign_in = সাইণ ইণ -sign_in_or = বা \ No newline at end of file +sign_in = সাইন ইন +sign_in_or = বা +sign_in_with_provider = %s দিয়ে সাইন-ইন করুন +sign_out = সাইন আউট +sign_up = নিবন্ধন করুন \ No newline at end of file diff --git a/options/locale/locale_ca.ini b/options/locale/locale_ca.ini index a3ea3843d7..be758e072c 100644 --- a/options/locale/locale_ca.ini +++ b/options/locale/locale_ca.ini @@ -1,6 +1,6 @@ [common] home = Inici -dashboard = Panell de control +dashboard = Tauler de control explore = Explorar help = Ajuda logo = Logotip @@ -23,7 +23,7 @@ enable_javascript = Aquest lloc web requereix Javascript. toc = Taula de Continguts licenses = Llicències sign_up = Registrar-se -link_account = Vincular un compte +link_account = Vincula un compte tracked_time_summary = Resum del temps registrat basat en filtres del llistat de temes return_to_forgejo = Tornar a Forgejo toggle_menu = Commuta el menú @@ -158,7 +158,7 @@ commit_kind = Cerca commits… runner_kind = Cerca executors… no_results = Cap resultat coincident trobat. keyword_search_unavailable = La cerca per paraula clau no està disponible ara mateix. Si us plau contacteu amb l'administrador del lloc. -union = Paraules clau +union = Unió union_tooltip = Inclou resultats que encaixen amb qualsevol paraula clau separada per espais org_kind = Cerca organitzacions… team_kind = Cerca teams… @@ -195,7 +195,7 @@ title = Configuració inicial docker_helper = Si executes Forgejo a Docker, si us plau llegeis la documentació abans de canviar qualsevol configuració. require_db_desc = Forgejo requereix de MySQL, PostreSQL, SQLite3 o TiDB (protocol MySQL). db_title = Configuració de la base de dades -path = Ruta +path = Camí sqlite_helper = Ruta al fitxer de la base de dades SQLite3.
Introduex la ruta absoluta si executes Forgejo com a servei. user = Nom d'usuari db_schema = Esquema @@ -206,7 +206,7 @@ reinstall_confirm_message = Reinstaŀlar amb una base de dades existent de Forge no_admin_and_disable_registration = No pot deshabilitar l'autoregistre d'usuaris sense crear un compte d'administrador. err_admin_name_is_reserved = El nom d'usuari "Administrador" no es vàlid: està reservat smtp_addr = Hoste SMTP -smtp_port = Port SMPT +smtp_port = Port SMTP smtp_from = Enviar correu com a mailer_user = Nom d'usuari SMTP err_admin_name_pattern_not_allowed = El nom d'usuari de l'administrador no es vàlid: coincideix amb un patró reservat @@ -246,25 +246,25 @@ admin_password = Contrasenya err_empty_admin_password = La contrasenya de l'administrador no por ser buida. ssh_port = Por del servidor SSH disable_gravatar = Deshabilitar Gravatar -disable_registration = Deshabilitar l'auto-registre +disable_registration = Deshabilita l'auto-registre openid_signin = Habilita l'inici de sessió amb OpenID enable_captcha = Habilita el CAPTCHA al registre -default_keep_email_private = Amaga les direccions de correu per defecte +default_keep_email_private = Amaga les adreces de correu, per defecte app_slogan = Eslogan de la instància app_slogan_helper = Escriu l'eslogan de la teva instància aquí. Deixa buit per deshabilitar. -repo_path = Ruta de l'arrel del repositori +repo_path = Camí arrel del repositori log_root_path_helper = Els arxius dels registres es s'escriuran en aquest directori. optional_title = Configuracions opcionals -host = Hoste +host = Amfitrió lfs_path = Ruta arreal de Git LFS -run_user = Executar com a usuari +run_user = Executa com a usuari domain_helper = Domini o adreça de l'hosta per al servidor. http_port = Port d'escolta HTTP app_url_helper = Adreces base per a clonació HTTP(S) i notificacions per correu. log_root_path = Ruta dels registres smtp_from_invalid = L'adreça d'"Enviar correu com a" és invalida smtp_from_helper = L'adreça de correu que Forgejo utilitzarà. Entri el correu en pla o en format "Nom" . -register_confirm = Requereix confirmació de correu per a registrar-se +register_confirm = Requereix una confirmació de correu per a registrar-se disable_gravatar.description = Deshabilitar l'ús de Gravatar o d'altres serveis d'avatars de tercers. S'utilitzaran imatges per defecte per als avatars dels uauris fins que pujin el seu propi a la instància. federated_avatar_lookup.description = Cerca d'avatars amb Libravatar. allow_only_external_registration = Permet el registre només amb serveis externs @@ -272,8 +272,8 @@ allow_only_external_registration.description = Els usuaris nomes podràn crear n enable_captcha.description = Requereix als usuaris passar el CAPTCHA per a poder-se crear comptes. require_sign_in_view = Requereix inciar sessió per a veure el contingut de la instància default_keep_email_private.description = Habilita l'ocultament de les direccions de correu per a nous usuaris per defecte, amb tal que aquesta informació no sigui filtrada immediatament despres de registrar-se. -default_allow_create_organization = Per defecte permet crear organitzacions -default_enable_timetracking = Per defecta habilita el seguiment de temps +default_allow_create_organization = Permet crear organitzacions, per defecte +default_enable_timetracking = Habilita el seguiment de temps, per defecte default_enable_timetracking.description = Per defecte activa el de seguiment de temps als nous repositoris. admin_name = Nom d'usuari de l'administrador install_btn_confirm = Instaŀlar Forgejo @@ -287,7 +287,7 @@ env_config_keys = configuració de l'entorn db_type = Tipus de base de dades lfs_path_helper = Els arxius seguits per Git LFS es desaran en aquest directory. Deixa buit per deshabilitar. http_port_helper = Numero de port que utilitzarà el servidor web de Forgejo. -repo_path_helper = Els repositoris Git remotes es desaran en aquest diectori. +repo_path_helper = Els repositoris Git remots es desaran en aquest directori. run_user_helper = El nom d'usuari del sistema operatiu sota el que Forgejo s'executa. Notis que aquest usuari ha de tenir accés a la ruta arrel del repositori. ssh_port_helper = Numero del port que utilitzarà el servidor SSH. Deixa buit per deshablitar el servidor SSH. require_sign_in_view.description = Limita l'accès al contingut per als usuaris connectats. Els visitatnts només podran veure les pàgines d'autenticació. @@ -380,7 +380,7 @@ email_domain_blacklisted = No podeu registrar-vos amb el correu electrònic. hint_login = Ja tens compte? Entra ara! hint_register = Necessites un compte? Registra't ara. sign_up_button = Registra't ara. -must_change_password = Actualitza la contrasenya +must_change_password = Actualitzeu la contrasenya change_unconfirmed_email_error = No s'ha pogut canviar l'adreça de correu: %v oauth_signup_tab = Registrar compte nou back_to_sign_in = Torneu a entrar @@ -397,7 +397,7 @@ twofa_passcode_incorrect = El codi d'accés és incorrecte. Si heu perdut el dis oauth_signin_tab = Vincular a un compte existent oauth.signin.error = Hi ha hagut un error processant la sol·licitud d'autorització. Si persisteix, poseu-vos en contacte amb l'administrador del lloc. disable_forgot_password_mail_admin = La recuperació de comptes només està disponible quan s'ha configurat el correu electrònic. Si us plau, configureu el correu electrònic per a habilitar la recuperació de comptes. -non_local_account = Els usuaris no locals no poden actualitzar la seva contrasenya mitjançant l'interfície web de Forgejo. +non_local_account = No es permet actualitzar la contrasenya dels usuaris externs (no locals) des de la pàgina web de Forgejo. openid_register_desc = No s'ha reconegut la URI OpenID. Vinculeu-la amb un compte nou aquí. openid_connect_desc = No s'ha reconegut la URI OpenID. Vinculeu-la amb un compte nou aquí. sign_in_openid = Accediu amb OpenID @@ -494,16 +494,16 @@ primary_mail_change.subject = S'ha canviat la vostra adreça de correu electròn totp_disabled.subject = S'ha deshabilitat TOTP removed_security_key.subject = S'ha eliminat una clau de seguretat removed_security_key.text_1 = S'ha eliminat la clau de seguretat "%[1]s" del vostre compte. -account_security_caution.text_1 = Podeu ignorar aquest correu si heu sigut vos. -account_security_caution.text_2 = Si no heu sigut vos, el vostre compte està compromès. Si us plau, contacteu els administradors d'aquest lloc. +account_security_caution.text_1 = Podeu ignorar aquest correu si heu sigut vós. +account_security_caution.text_2 = Si no heu sigut vós, el vostre compte està compromès. Si us plau, contacteu els administradors d'aquest lloc. totp_enrolled.subject = Heu activat TOTP com a mètode d'autenticació de doble factor totp_enrolled.text_1.no_webauthn = Heu activat TOTP pel vostre compte. Això vol dir que haureu d'usar TOTP com a mètode d'autenticació de doble factor a tots els inicis de sessió futurs al vostre compte. issue_assigned.pull = @%[1]s us ha assignat la sol·licitud d'extracció %[2]s al repositori %[3]s. issue.action.reopen = @%[1]s ha reobert #%[2]s. issue.action.approve = @%[1]s ha aprovat aquesta sol·licitud d'extracció. issue.action.reject = @%[1]s ha sol·licitat canvis en aquesta sol·licitud d'extracció. -register_notify.text_2 = Podeu iniciar sessió al vostre compte fent servir el vostre nom d'usuari: %s -register_notify.text_1 = aquest és el vostre correu electrònic de confirmació pel registre de %s! +register_notify.text_2 = Pots iniciar sessió al teu compte utilitzant el teu usuari: %s +register_notify.text_1 = aquest és el teu correu electrònic de confirmació per %s! password_change.text_1 = S'acaba de canviar la contrasenya pel vostre compte. issue.action.review = @%[1]s ha deixat un comentari a la vostra sol·licitud d'extracció. issue.action.review_dismissed = @%[1]s ha rebutjat l'última revisió de %[2]s per aquesta sol·licitud d'extracció. @@ -511,16 +511,16 @@ primary_mail_change.text_1 = S'ha canviat la vostra adreça de correu electròni totp_disabled.text_1 = S'han desactivat les contrasenyes d'un sol ús basades en el temps (TOTP) pel vostre compte. totp_disabled.no_2fa = Ja no hi ha altres mètodes d'autenticació de doble factor configurats, per la qual cosa ja no és necessari iniciar sessió al vostre compte mitjançat autenticació de doble factor. removed_security_key.no_2fa = Ja no hi ha altres mètodes d'autenticació de doble factor configurats, per la qual cosa ja no és necessari iniciar sessió al vostre compte mitjançat autenticació de doble factor. -reset_password = Recupereu el vostre compte +reset_password = Recuperar el vostre compte reset_password.text = Si heu sigut vós, cliqueu el següent enllaç per recuperar el vostre compte abans de %s: -totp_enrolled.text_1.has_webauthn = Heu habilitat el TOTP per al vostre compte. Això vol dir que, per a totes les futures connexions al vostre compte, podreu utilitzar el TOTP com a mètode d'autenticació en dos passos (2FA) o bé utilitzar qualsevol de les vostres claus de seguretat. +totp_enrolled.text_1.has_webauthn = Heu activat TOTP pel vostre compte. Això vol dir que podreu usar TOTP com a mètode d'autenticació de doble factor a tots els inicis de sessió futurs al vostre compte, o bé usar qualsevol de les vostres claus de seguretat. issue.action.force_push = %[1]s ha realitzat un «force push» de %[2]s des de %[3]s fins a %[4]s. issue.action.ready_for_review = @%[1]s ha marcat aquesta «pull request» com a preparada per a la revisió. issue.in_tree_path = A %s: issue.action.push_1 = @%[1]s ha pujat $[3]d commit a %[2]s issue.action.push_n = @%[1]s ha pujat $[3]d commits a %[2]s release.note = Nota: -release.new.text = @%[1]s ha publicat %[2]s a %[3]s +release.new.text = @%[1]s ha publicat %[2]s en %[3]s release.new.subject = %s a %s publicat [modal] @@ -554,7 +554,7 @@ last_org_owner = No podeu eliminar l'últim usuari de l'equip "propietaris". Una duplicate_invite_to_team = L'usuari ja ha estat convidat com a membre de l'equip. Biography = Biografia RepoName = Nom del repositori -TeamName = Nom de l' equip +TeamName = Nom de l'equip To = Nom de la branca NewBranchName = Nom de la nova branca Content = Contingut @@ -611,12 +611,21 @@ git_ref_name_error = ` ha de ser un nom correcte de referència de Git.` size_error = ` ha de tenir una mida de %s.` include_error = ` ha de contenir la subcadena «%s».` glob_pattern_error = ` el patró glob no és vàlid: %s.` -username_error = ` només pot contenir caràcters alfanumèrics ("0-9","a-z","A-Z"), guió ("-"), barra baixa ("_") i punt ("."). No pot començar ni acabar amb caràcters no alfanumèrics, i els caràcters no alfanumèrics consecutius també estan prohibits.` +username_error = ` pot contenir només caràcters alfanumèrics ("0-9","a-z","A-Z"), barres baixes ("_") i punts ("."). No pot començar ni acabar amb caràcters que no siguin alfanumèrics, i els caràcters que no siguin alfanumèrics tampoc poden aparèixer de manera consecutiva.` username_error_no_dots = ` només pot contenir caràcters alfanumèrics ("0-9","a-z","A-Z"), guió ("-") i barra baixa ("_"). No pot començar ni acabar amb caràcters no alfanumèrics, i els caràcters no alfanumèrics consecutius tampoc estan permesos.` -username_claiming_cooldown = El nom d'usuari no es pot reservar degut a que el seu període de refredament encara no ha acabat. Es podrà fer servir en %[1]s. +username_claiming_cooldown = No es pot reclamar el nom d'usuari perquè el seu període de temps de recuperació encara no ha acabat. Es podrà reclamar el %[1]s. invalid_group_team_map_error = ` el mapatge no és vàlid: %s` repository_force_private = S'ha activat "Forçar privat": els repositoris privats no es poden fer públics. +2fa_auth_required = L'accés remot requereix una autenticació de doble factor. + +visit_rate_limit = S'ha sobrepassat la taxa de visita remota. +unset_password = L'usuari no ha establert una contrasenya. + +team_no_units_error = Permet l'accés a una secció del repositori com a mínim. +unsupported_login_type = El tipus d'accés no permet eliminar el compte. +invalid_ssh_principal = Principal invàlid: %s + [settings] pronouns = Pronoms change_username_prompt = Nota: canviar el vostre nom d'usuari també canvia l'URL del vostre compte. @@ -670,7 +679,7 @@ twofa = Autenticació de doble factor (TOTP) webauthn = Autenticació de doble factor (claus de seguretat) storage_overview = Vista general de l'emmagatzematge quota = Quota -profile_desc = Sobre vos +profile_desc = Sobre vós password_username_disabled = Els usuaris no locals no tenen permès canviar el seu nom d'usuari. Si us plau, contacteu el vostre administrador per saber-ne més. update_profile = Actualitzar el perfil update_language = Canviar l'idioma @@ -702,7 +711,7 @@ theme_desc = Aquest tema s'usarà per a la interfície web quan hàgiu iniciat s activated = Activat requires_activation = Requereix activació activations_pending = Activacions pendents -can_not_add_email_activations_pending = Hi ha una activació pendent, proveu de nou en uns minuts si voleu afegir un nou correu electrònic. +can_not_add_email_activations_pending = Hi ha una activació pendent. Si voleu afegir una nova adreça de correu electrònic, proveu-ho de nou en uns minuts. email_deletion = Elimina l'adreça de correu electrònic email_deletion_desc = Aquesta adreça de correu electrònic i la informació relacionada s'eliminaran del vostre compte. Els commits de Git fets amb ella romandran sense canvis. Continuar? email_deletion_success = S'ha eliminat l'adreça de correu electrònic. @@ -774,7 +783,7 @@ generate_token = Generar el testimoni generate_token_success = S'ha generat el vostre nou testimoni. Copieu-lo ara, ja que no es tornarà a mostrar. generate_token_name_duplicate = Ja s'ha usat %s com a nom d'aplicació. Si us plau, useu-ne un de nou. delete_token = Eliminar -access_token_deletion = +access_token_deletion =Esborra el testimoni d'accés delete_email = Eliminar biography_placeholder = Explica una mica sobre tu als altres! (Compatible amb Markdown) add_new_email = Afegir una adreça de correu electrònic @@ -833,7 +842,7 @@ twofa_scratch_token_regenerate = Regenerar la clau de recuperació d'un sol ús twofa_scratch_token_regenerated = La vostra clau de recuperació d'un sol ús ara és %s. Emmagatzemeu-la en un lloc segur, ja que no es tornarà a mostrar. twofa_disable_note = L'autenticació de doble factor es pot desactivar si és necessari. twofa_disable_desc = Desactivar l'autenticació de doble factor farà que el vostre compte sigui menys segur. Voleu continuar? -regenerate_scratch_token_desc = Si heu perdur la vostra clau de recuperació o ja l'heu fet servir per iniciar sessió, la podeu reiniciar aquí. +regenerate_scratch_token_desc = Si heu perdut la vostra clau de recuperació o ja l'heu fet servir per iniciar sessió, la podeu reiniciar aquí. twofa_disabled = S'ha desactivat l'autenticació de doble factor. scan_this_image = Escanegeu aquesta imatge amb la vostra aplicació d'autenticació: or_enter_secret = O introduïu el secret: %s @@ -875,18 +884,77 @@ quota.sizes.assets.attachments.issues = Fitxers adjunts a incidències quota.sizes.assets.artifacts = Artefactes quota.sizes.assets.packages.all = Paquets enable_custom_avatar = Usa un avatar personalitzat -comment_type_group_assignee = Assignat +comment_type_group_assignee = Assignatari visibility.public = Públic visibility.limited = Limitat visibility.private = Privat primary = Principal +lookup_avatar_by_mail = Cercar l'avatar amb l'adreça de correu electrònic +access_token_desc = Els permisos de testimoni seleccionats es limiten a les rutes API corresponents. Llegiu la documentació per a més informació. +oauth2_confidential_client = Client confidencial. Seleccioneu aquesta opció per a aplicacions que mantinguin el secret confidencial, com les aplicacions web. No la seleccioneu pas per a aplicacions nadiues, tant d'escriptori com mòbils. +oauth2_application_create_description = Les aplicacions OAuth2 permeten que les vostres aplicacions de tercers accedeixin als comptes d'usuari d'aquesta instància. +oauth2_application_remove_description = Esborrar una aplicació OAuth2 li denegarà l'accés als comptes d'usuari autoritzats d'aquesta instància. Voleu continuar? +oauth2_application_locked = Forgejo registra per defecte algunes aplicacions OAuth2 en arrencar, si s'habilita a la configuració. Per evitar un comportament inesperat, aquestes aplicacions no es poden editar o eliminar. Si us plau, aneu a la documentació de l'OAuth2 per a més informació. +twofa_is_enrolled = El vostre compte té actualment activada l'autenticació de doble factor. +twofa_not_enrolled = El vostre compte no ha activat l'autenticació de doble factor. +twofa_enroll = Activar l'autenticació de doble factor +twofa_enrolled = S'ha activat satisfactòriament l'autentificació de doble factor per al vostre compte. Deseu la vostra clau de recuperació d'un sol ús (%s) en un lloc segur, ja que no es mostrarà més vegades. +hooks.desc = Afegir webhooks que s'executaran per a tots els repositoris que teniu. +delete_with_all_comments = El vostre compte és més recent que %s. Per evitar comentaris fantasma, tots els comentaris de problemes/PR s'eliminaran. +email_notifications.submit = Establir la preferència de correu electrònic +email_notifications.andyourown = I les vostres pròpies notificacions +visibility = Visibilitat d'usuari +quota.rule.exceeded.helper = La mida total dels objectes per a aquesta norma ha superat la quota. +quota.rule.no_limit = Il·limitat +quota.sizes.all = Tot +quota.sizes.assets.all = Recursos +quota.sizes.wiki = Wiki + +user_block_yourself = No us podeu bloquejar. +quota.applies_to_user = Les regles de quota següents s'apliquen al vostre compte +quota.applies_to_org = Les regles de quota següents s'apliquen a aquesta organització +quota.rule.exceeded = Sobrepassat + +change_username_redirect_prompt.with_cooldown.one = El nom d'usuari antic estarà disponible per a tothom després d'%[1]d dia. Podeu reclamar-lo abans que passi aquest temps. +change_username_redirect_prompt.with_cooldown.few = El nom d'usuari antic estarà disponible per a tothom després de %[1]d dies. Podeu reclamar-lo abans que passi aquest temps. +additional_repo_units_hint_description = Mostra un suggeriment per "Habilitar-ne més" pels repositoris que no tenen habilitades totes les unitats. +comment_type_group_lock = Estat del bloqueig +choose_new_avatar = Escolliu un nou avatar +primary_email = Fer-la principal +activate_email = Enviar l'activació +email_preference_set_success = S'ha configurat correctament la preferència de correu electrònic. +keep_email_private_popup = La vostra adreça de correu electrònic no es mostrarà al vostre perfil i no serà la predeterminada pels commits fets mitjançat la interfície web, com ara pujades de fitxers, modificacions i commits de fusió. En el seu lloc, una adreça especial %s es pot fer servir per enllaçar commits al vostre compte. Aquesta opció no afectarà els commits ja existents. +manage_ssh_principals = Gestiona els Certificats de Principals SSH +add_key = Afegir una clau +principal_desc = Aquests certificats principals d'SSH són associats al vostre compte i permeten accés complet als vostres repositoris. +add_new_principal = Afegir principal +ssh_principal_been_used = Aquest principal ja s'ha afegit al servidor. +gpg_key_matched_identities_long = Les identitats incrustades en aquesta clau coincideixen amb les següents adreces de correu electrònic activades per aquest usuari. Els commits coincidents amb aquestes adreces de correu electrònic es poden verificar amb aquesta clau. +gpg_token_signature = Firma GPG blindada +ssh_token_signature = Firma SSH blindada +add_principal_success = S'ha afegit el certificat principal SSH "%S". +ssh_principal_deletion = Eliminar Certificat Principal SSH +ssh_key_deletion_desc = Eliminar una clau SSH en revocarà l'accés al vostre compte. Voleu continuar? +gpg_key_deletion_desc = Eliminar una clau GPG des-verificarà els commits firmats per ella. Voleu continuar? +ssh_principal_deletion_desc = Eliminar un Certificat Principal SSH revoca el seu accés al vostre compte. Continuar? +ssh_principal_deletion_success = S'ha eliminat el principal. +valid_until_date = Vàlid fins %s +principal_state_desc = Aquest principal s'ha usat en els darrers 7 dies +repo_and_org_access = Accés al repositori i a l'organització +webauthn_delete_key = Eliminar la clau de seguretat +webauthn_alternative_tip = Segurament voldreu configurar un mètode d'autenticació addicional. +remove_account_link = Eliminar un compte vinculat +email_notifications.onmention = Enviar correus electrònics només quan se us mencioni +blocked_since = Bloquejat des de %s +quota.sizes.assets.attachments.releases = Fitxers adjunts a la publicació + [repo] settings.basic_settings = Configuració bàsica settings.event_issues = Modificació settings.web_hook_name_msteams = Microsoft Teams settings.tracker_issue_style.numeric = Numèric -settings.allow_only_contributors_to_track_time = Permet només als contribuidors fer un seguiment del temps +settings.allow_only_contributors_to_track_time = Fes que només els contribuïdors puguin fer un seguiment de temps settings.admin_stats_indexer = Indexador d'estadístiques del codi settings.admin_code_indexer = Indexador del codi issue_labels = Etiquetes @@ -1280,7 +1348,7 @@ pulls = Sol·licituds d'extracció project = Projectes org_labels_desc = Etiquetes de nivell d'organització que es poden usar amb tots els repositoris dins d'aquesta organització released_this = ha publicat això -file_view_source = Veure la font +file_view_source = Veure el codi font file_too_large = El fitxer és massa gran per ser mostrat. invisible_runes_header = `Aquest fitxer conté caràcters Unicode invisibles` invisible_runes_description = `Aquest fitxer conté caràcters Unicode invisibles que són indistingibles pels humans però que un ordinador pot processar de manera diferent. Si creieu que això és intencional, podeu ignorar aquest avís. Useu el botó Esc per revelar-los.` @@ -1325,7 +1393,7 @@ editor.fail_to_apply_patch = No s'ha pogut aplicar el pedaç "%s" editor.new_patch = Pedaç nou editor.commit_message_desc = Afegiu una descripció ampliada opcional… editor.create_new_branch_np = Crear una nova branca per aquest commit. -editor.create_new_branch = Crear una nova branca per aquest commit i iniciar una sol·licitud d'extracció. +editor.create_new_branch = Creeu una nova branca per aquest commit i inicieu una sol·licitud d'extracció. editor.new_branch_name_desc = Nom de la branca nova… editor.filename_is_invalid = El nom del fitxer és incorrecte: "%s". editor.branch_does_not_exist = La branca "%s" no existeix en aquest repositori. @@ -1395,7 +1463,7 @@ issues.reaction.alt_many = %[1]s i %[2]d més han reaccionat %[3]s. issues.reaction.alt_remove = Eliminar %[1]s reacció del comentari. issues.reaction.alt_add = Afegir %[1]s reacció al comentari. issues.context.copy_link = Copiar l'enllaç -issues.context.quote_reply = +issues.context.quote_reply =Citar la resposta issues.context.reference_issue = Referenciar-la en una nova incidència issues.no_content = No s'ha proporcionat cap descripció. issues.close = Tancar la incidència @@ -1438,7 +1506,7 @@ issues.lock_duplicate = No es pot bloquejar una incidència dues vegades. issues.unlock_error = No es pot desbloquejar una incidència que no està bloquejada. issues.unlock_comment = ha desbloquejat aquesta conversa %s issues.lock.notice_1 = - Els altres usuaris no podran deixar més comentaris en aquesta incidència. -issues.lock.notice_2 = - Vos i altres col·laboradors amb accés a aquest repositori encara podeu deixar comentaris que els altres poden veure. +issues.lock.notice_2 = - Vós i altres col·laboradors amb accés a aquest repositori encara podeu deixar comentaris que els altres poden veure. issues.lock.notice_3 = - Sempre podeu desbloquejar aquesta incidència una altra vegada més endavant. issues.unlock.notice_1 = - Tothom podrà tornar a deixar comentaris en aquesta incidència. issues.unlock.notice_2 = - Sempre podeu bloquejar aquesta incidència una altra vegada més endavant. @@ -1498,7 +1566,7 @@ pulls.merge_conflict = La fusió ha fallat: hi ha hagut un conflicte durant la f pulls.merge_conflict_summary = Missatge d'error pulls.rebase_conflict_summary = Missatge d'error signing.wont_sign.approved = La fusió no es signarà perquè la sol·licitud d'extracció no està aprovada. -signing.wont_sign.not_signed_in = No heu iniciat sessió. +signing.wont_sign.not_signed_in = No teniu la sessió iniciada. ext_wiki = Wiki externa wiki.welcome = Benvingut/da a la wiki. wiki.welcome_desc = La wiki us permet escriure i compartir documentació amb els col·laboradors. @@ -1541,7 +1609,7 @@ activity.new_issues_count_n = Noves incidències activity.title.unresolved_conv_1 = %s conversa sense resoldre activity.title.unresolved_conv_n = %s converses sense resoldre activity.unresolved_conv_desc = Aquestes incidències i sol·licituds d'extracció recentment modificades no han sigut resoltes encara. -activity.title.releases_1 = %d entrega +activity.title.releases_1 = %d publicació activity.title.releases_n = %d entregues activity.title.releases_published_by = %s publicada per %s activity.published_tag_label = Etiqueta @@ -1558,7 +1626,1005 @@ activity.git_stats_addition_1 = %d addició activity.git_stats_addition_n = %d addicions activity.git_stats_deletion_1 = %d eliminació activity.git_stats_deletion_n = %d eliminacions -settings.mirror_settings.docs = Configureu el vostre repositori per sincronitzar automàticament commits, etiquetes i branques amb un altre repositori. +settings.mirror_settings.docs = Configureu el vostre repositori per sincronitzar commits, etiquetes i branques automàticament amb un altre repositori. + +rss.must_be_on_branch = Heu d'estar en una branca per a tenir un canal RSS. +admin.manage_flags = Gestiona les marques +admin.enabled_flags = Marques habilitades del repositori: +admin.update_flags = Actualitza les marques +admin.failed_to_replace_flags = No s'han pogut reemplaçar les marques del repositori +admin.flags_replaced = S'han reemplaçat les marques del repositori +new_repo_helper = Un repositori conté tots els arxius del projecte, incloent l'historial de revisions. Ja n'esteu allotjant un en un altre lloc? Migració de repositori. +new_from_template = Usar una plantilla +size_format = %[1]s: %[2]s; %[3]s: %[4]s +visibility_helper = Fer el repositori privat +use_template = Usar aquesta plantilla +license_helper_desc = Una llicència estableix què poden fer o no les altres persones amb el vostre codi. Si no esteu segur de quina és la més adequada per al vostre projecte, aneu a Choose a license. +object_format = Format d'objecte +object_format_helper = Format d'objecte del repositori. No es pot canviar després. SHA1 és el format més compatible. +auto_init = Inicialitzar el repositori +auto_init_description = Comença l'historial de Git amb un README i, opcionalment, afegeix un arxiu de llicència i .gitignore. +create_repo = Crear un repositori +mirror_use_ssh.text = Usar l'autenticació SSH +mirror_denied_combination = No es poden usar simultàniament una autenticació per clau pública i per contrasenya. +stars_remove_warning = Això eliminarà totes les estrelles d'aquest repositori. +archive.pull.noreview = Aquest repositori està arxivat. No podeu revisar-ne les «pull requests». +sync_fork.branch_behind_one = Aquesta branca és %[1]d commit darrere de %[2]s +sync_fork.branch_behind_few = Aquesta branca és %[1]d commits darrere de %[2]s +form.reach_limit_of_creation_1 = El propietari ja ha superat el límit de %d repositori. +form.reach_limit_of_creation_n = El propietari ja ha superat el límit de %d repositoris. +form.name_reserved = El nom de repositori "%s" està reservat. +form.name_pattern_not_allowed = El patró "%s" no està permès en el nom del repositori. +form.string_too_long = El text introduït té més de %d caràcters. +migrate_options = Opcions de migració +migrate_options_mirror_helper = Aquest repositori serà un mirall +migrate_options_lfs_endpoint.description.local = També s'accepta un camí al servidor local. +migrate_items = Elements de migració + +open_with_editor = Obre amb %s +mirror_prune_desc = Elimina les referències de seguiment remot obsoletes +mirror_sync_on_commit = Sincronitza quan es pugin commits +mirror_lfs = Emmagatzematge gran de fitxers (LFS) +mirror_lfs_desc = Activa l'emmirallament de dades LFS. +mirror_lfs_endpoint = Punt final LFS +mirror_lfs_endpoint_desc = En sincronitzar, s'intentarà utilitzar l'url de clonatge per a determinar el servidor LFS. També podeu especificar un punt final personalitzat si les dades LFS del repositori són en un altre lloc. +mirror_password_help = Canvia el nom d'usuari per esborrar una contrasenya desada. +adopt_search = Entra el nom d'usuari per cercar repositoris no-adoptats... (deixeu-ho en blanc per cercar-los tots) +adopt_preexisting_label = Adopta fitxers +adopt_preexisting = Adopta fitxers preexistents +adopt_preexisting_content = Crea un repositori des de %s +adopt_preexisting_success = Fitxers adoptats i repositori creat des de %s +delete_preexisting = Elimina fitxers preexistents +delete_preexisting_content = Elimina fitxers en %s +template.git_hooks_tooltip = Actualment no podeu modificar o eliminar els ganxos git un cop s'han afegit. Només selecciona això si confieu en el repositori de plantilla. +template.one_item = Heu de seleccionar un ítem de plantilla com a mínim +template.invalid = Heu de seleccionar un repositori de plantilla +archive.title = Aquest repositori és un arxiu. Podeu veure-hi els fitxers i clonar-lo, però no podeu fer-hi canvis com pujar modificacions, crear-ne incidències, «pull requests» o comentaris. +archive.title_date = Aquest repositori és un arxiu a %s. Podeu veure-hi els fitxers i clonar-lo, però no podeu fer-hi canvis com pujar modificacions, crear-ne incidències, «pull requests» o comentaris. +archive.nocomment = No es poden crear comentaris perquè el repositori és un arxiu. +sync_fork.button = Sincronitza +migrate_options_lfs = Migra els fitxers LFS +migrate_options_lfs_endpoint.label = Punt final LFS +migrate_options_lfs_endpoint.description = En migrar, s'intentarà utilitzar el vostre remot git per a determinar el servidor LFS. També podeu especificar un punt final personalitzat si les dades LFS del repositori són en un altre lloc. +migrate_options_lfs_endpoint.placeholder = Si ho deixeu en blanc, el punt final derivarà de l'URL de clonació +migrate_items_pullrequests = Pull requests + +fork_repo = Bifurca el repositori +fork_from = Bifurcar des de +repo_gitignore_helper_desc = Escolliu de quins fitxers no s'ha de fer seguiment d'una llista de plantilles per llenguatges comuns. Els artefactes típics generats per les eines de construcció de cada llenguatge estan incloses al .gitignore de manera predeterminada. +readme_helper_desc = Aquí podeu escriure una descripció completa del vostre projecte. +default_branch_helper = La branca per defecte és la branca base pels pull requests i els commits. +mirror_interval = Interval de rèplica (les unitats de temps vàlides són "h", "m", "s"). 0 per desactivar la sincronització periòdica. (Interval mínim: %s) +mirror_use_ssh.helper = Si seleccioneu aquesta opció, Forgejo replicarà el repositori mitjançant Git per SSH i us crearà una parella de claus. Heu d'assegurar-vos que la clau pública generada estigui autoritzada per publicar al repositori de destí. No podreu fer servir autenticació basada en contrasenyes. +delete_preexisting_success = S'ha suprimit els fitxers no-adoptats a %s +blame_prior = Veure el «blame» anterior a aquest canvi +blame.ignore_revs = S'ignoren les revisions a .git-blame-ignore-revs. Fes clic aquí per veure-les. +blame.ignore_revs.failed = No s'han pogut ignorar les revisions a .git-blame-ignore-revs. +author_search_tooltip = Es mostra un màxim de 30 usuaris +summary_card_alt = Resum del repositori %s +tree_path_not_found.commit = El camí %[1]s no existeix al commit %[2]s +tree_path_not_found.branch = El camí %[1]s no existeix a la branca %[2]s +tree_path_not_found.tag = El camí %[1]s no existeix a l'etiqueta %[2]s +transfer.accept = Accepta la transferència +transfer.accept_desc = Transfereix a "%s" +transfer.reject = Denega la transferència +transfer.reject_desc = Cancel·la la transferència a "%s" +transfer.no_permission_to_accept = No teniu permisos per acceptar aquesta transferència. +transfer.no_permission_to_reject = No teniu permisos per denegar aquesta transferència. +template.items = Ítems de la plantilla +template.git_content = Contingut Git (Branca predeterminada) +template.git_hooks = Ganxos Git +migrate_items_merge_requests = Sol·licituds de fusió +migrate_repo = Migra el repositori +migrate.repo_desc_helper = Deixa-ho buit per importar la descripció existent +migrate.clone_address = Migra / Clona des d'una URL +migrate.clone_address_desc = L'URL d'HTTP(S) o de Git "clone" d'un repositori ja existent +migrate.github_token_desc = Podeu posar un o més testimonis separats amb comes per fer que la migració sigui més ràpida, evitant així el límit de taxa de l'API de GitHub. ATENCIÓ: Abusar aquesta funció pot anar en contra de la política de servei del proveïdor i pot comportar el bloqueig del/s vostre/s compte/s. +migrate.clone_local_path = o el camí a un servidor local +migrate.permission_denied = No podeu importar repositoris locals. +migrate.permission_denied_blocked = No podeu importar des d'amfitrions rebutjats, si us plau, demaneu a l'administrador que comprovi les configuracions ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS. +migrate.invalid_local_path = El camí local és invàlid. No existeix o no és un directori. +migrate.invalid_lfs_endpoint = El punt final LFS no és vàlid. +migrate.failed = La migració ha fallat: %v +migrate.migrate_items_options = Cal un testimoni d'accés per migrar els ítems addicionals +migrated_from = Migrat des de %[2]s +migrated_from_fake = Migrat des de %[1]s +migrate.migrate = Migra des de %s +migrate.migrating = S'està migrant des de %s … +migrate.migrating_failed = La migració des de %s ha fallat. +migrate.migrating_failed.error = No s'ha pogut migrar: %s +migrate.migrating_failed_no_addr = La migració ha fallat. +migrate.migrating_git = Migrant dades Git +migrate.migrating_topics = Migrant tòpics +migrate.migrating_milestones = Migrant fites +migrate.migrating_labels = Migrant etiquetes +migrate.migrating_releases = Migrant publicacions +migrate.migrating_issues = Migrant problemes +migrate.migrating_pulls = Migrant «pull requests» +migrate.cancel_migrating_title = Cancel·la la migració +migrate.cancel_migrating_confirm = Voleu cancel·lar aquesta migració? +mirror_from = mirall de +forked_from = bifurcat des de +generated_from = generat des de +fork_from_self = No podeu bifurcar un repositori que us pertany. +fork_guest_user = Inicia sessió per bifurcar aquest repositori. +watch_guest_user = Inicia sessió per vigilar aquest repositori. +star_guest_user = Inicia sessió per destacar aquest repositori. +subscribe.issue.guest.tooltip = Inicia sessió per subscriure't a aquest problema. +subscribe.pull.guest.tooltip = Inicia sessió per subscriure't a aquesta «pull request». +more_operations = Més operacions +no_desc = Sense descripció +quick_guide = Guia ràpida +clone_this_repo = Clona aquest repositori +cite_this_repo = Cita aquest repositori +create_new_repo_command = Crea un nou repositori a la línia de comandes +push_exist_repo = Puja un repositori ja existent des de la línia de comandes +empty_message = Aquest repositori està buit. +broken_message = Les dades Git d'aquest repositori no es poden llegir. Contacta amb l'administrador d'aquesta instància o suprimeix aquest repositori. +code.desc = Accedeix al codi font, els fitxers, els commits i les branques. +clear_ref = `Esborra la referència actual` +filter_branch_and_tag = Filtra per branca o etiqueta +find_tag = Cerca etiqueta +n_commit_one = %s commit +n_commit_few = %s commits +n_branch_one = Branca %s +n_branch_few = Branques %s +n_tag_one = Etiqueta %s +n_tag_few = Etiquetes %s +n_release_one = Publicació %s +n_release_few = Publicacions %s +file.title = %s a %s +file_follow = Seguir l'enllaç simbòlic +file_view_rendered = Veure renderitzat +file_view_raw = Veure cru +escape_control_characters =Escapar +commit_graph = Gràfic de commits +commit.contained_in = Aquest commit és a: +no_eol.text = Sense EOL +editor.commit_signed_changes = Fes un commit signat dels canvis +editor.commit_changes = Fes un commit dels canvis +editor.add_tmpl.filename = nom del fitxer +editor.update = Actualitzar %s +editor.patch = Aplicar pedaç +editor.patching = Aplicant el pedaç a: +editor.signoff_desc = Afegeix un "Signat per" seguit de l'autor al final del missatge del commit. +editor.commit_directly_to_this_branch = Feu un commit directament a la branca %[1]s. +editor.new_branch_name = Anomena la nova branca per a aquest commit +editor.file_already_exists = Ja hi ha un fitxer anomenat "%S" en aquest repositori. +editor.commit_id_not_matching = El fitxer ha canviat mentre l'editaves. Fes un commit a una nova branca i llavors fusiona-la. +editor.push_out_of_date = La pujada està desactualitzada. +editor.commit_empty_file_header = Fes un commit d'un fitxer buit +editor.user_no_push_to_branch = L'usuari no pot pujar a la branca +editor.cherry_pick = Triar a dit %s a: +editor.revert = Retorna %s a: +editor.commit_email = Adreça electrònica del commit +commits.no_commits = No hi ha commits en comú. "%s" i "%s" tenen històries completament diferents. +commits.signed_by_untrusted_user_unmatched = Signat per un usuari no fiable que no coincideix amb l'autor del commit +commits.view_path = Veure en aquest punt de la història +commits.view_single_diff = Veure els canvis fets en aquest fitxer introduïts en aquest commit +commit.revert-header = Retorna: %s +commit.revert-content = Selecciona una branca per retornar-hi: +commit.cherry-pick = Triar a dit +commit.cherry-pick-header = Triar a dit: %s +commit.cherry-pick-content = Seleccioneu una branca per triar-hi: +projects.new_subheader = Coordineu, feu seguiment, i actualitzeu el vostre treball en un sol lloc, per tal que els projectes es mantinguin transparents i dins del calendari previst. +projects.type.basic_kanban = Kanban bàsic +projects.type.bug_triage = Triatge d'errors +projects.column.set_default = Definir com a predeterminada +projects.column.set_default_desc = Estableix aquesta columna com a predeterminada per als problemes i pulls sense categoria +projects.column.assigned_to = Assignat a +projects.card_type.desc = Previsualització de targeta +issues.filter_assignees = Filtrar assignats +issues.filter_reviewers = Filtrar revisor +issues.new.open_projects = Projectes oberts +issues.new.open_milestone = Fites obertes +issues.new.clear_assignees = Esborra assignats +issues.new.no_assignees = Sense assignats +issues.new.assign_to_me = Assigna-m'ho +issues.new.no_reviewers = Sense revisors +issues.edit.already_changed = No s'han pogut desar els canvis al problema. Sembla que un altre usuari n'ha modificat el contingut. Si us plau, refresqueu la pàgina i intenteu-ho un altre cop per evitar reescriure els seus canvis +issues.choose.get_started = Començar +issues.choose.blank_about = Crea un problema a partir de la plantilla per defecte. +issues.choose.invalid_config = La configuració del problema té errors: +issues.label_templates.use = Utilitza una etiqueta predeterminada +issues.label_templates.fail_to_load_file = No s'ha pogut carregar el fitxer d'etiqueta predeterminada "%s": %v +issues.add_label = s'ha afegit l'etiqueta %s %s +issues.add_labels = s'han afegit les etiquetes %s %s +issues.remove_label = s'ha esborrat l'etiqueta %s %s +issues.remove_labels = s'han esborrat les etiquetes %s %s +issues.add_remove_labels = s'han afegit %s etiquetes i esborrat %s %s +issues.add_milestone_at = `s'ha afegit a la fita %s %s` +issues.add_project_at = `s'ha afegit al projecte %s %s` +issues.change_milestone_at = `s'ha modificat la fita des de %s a %s %s` +issues.change_project_at = `s'ha modificat el projecte des de %s a %s %s` +issues.remove_milestone_at = `s'ha eliminat de la fita %s %s` +issues.remove_project_at = `s'ha eliminat del projecte %s %s` +issues.self_assign_at = `s'ha auto-assignat aquest %s` +issues.add_assignee_at = `va ser assignat per %s %s` +issues.remove_assignee_at = `va ser desassignat per %s %s` +issues.remove_self_assignment = `s'ha eliminat la seva tasca %s` +issues.change_title_at = `s'ha canviat el títol de %s a %s %s` +issues.change_ref_at = `s'ha canviat la referència de %s a %s %s` +issues.remove_ref_at = `s'ha eliminat la referència %s %s` +issues.add_ref_at = `s'ha afegit la referència %s %s` +issues.delete_branch_at = `s'ha eliminat la branca %s %s` +issues.filter_label_no_select = Totes les etiquetes +issues.filter_label_select_no_label = Sense etiqueta +issues.filter_milestone_none = Sense fites +issues.filter_milestone_open = Fites obertes +issues.filter_milestone_closed = Fites tancades +issues.filter_project_all = Tots els projectes +issues.filter_project_none = Sense projecte +issues.filter_assginee_no_select = Tots els assignats +issues.filter_assginee_no_assignee = Sense assignat +issues.filter_poster_no_select = Tots els autors +issues.filter_type.all_pull_requests = Totes les «pull requests» +issues.filter_type.all_issues = Tots els problemes +issues.filter_type.assigned_to_you = Tasques que tens assignades +issues.filter_type.created_by_you = Creat per tu +issues.filter_type.mentioning_you = Que et mencionen +issues.filter_type.review_requested = S'ha demanat la revisió +issues.filter_type.reviewed_by_you = Revisats per tu +issues.filter_sort.relevance = Rellevància +issues.filter_sort.recentupdate = Actualitzats recentment +issues.filter_sort.leastupdate = Actualitzats menys recentment +issues.filter_sort.mostcomment = Les més comentades +issues.filter_sort.leastcomment = Menys comentats +issues.filter_sort.nearduedate = A prop de la data de venciment +issues.filter_sort.farduedate = Lluny de la data de venciment +issues.filter_sort.moststars = Més destacats +issues.filter_sort.feweststars = Menys destacats +issues.filter_sort.mostforks = Més bifurcacions +issues.filter_sort.fewestforks = Menys bifurcacions +issues.action_assignee_no_select = Sense assignat +pulls.merged_by = per %[3]s s'ha fusionat %[1]s +issues.closed_by = per %[3]s s'ha tancat %[1]s +issues.context.menu = Menú de comentari +issues.comment_pull_merged_at = s'ha fusionat el commit %[1]s a %[2]s %[3]s +issues.comment_manually_pull_merged_at = s'ha fusionat el commit %[1]s manualment a %[2]s %[3]s +issues.role.contributor_helper = Aquest usuari ja ha fet commits en aquest repositori. +issues.is_stale = Hi ha hagut canvis a aquest PR des de la revisió +issues.label_exclusive_desc = Doneu nom a l'àmbit/ítem de l'etiqueta per fer-la mútuament exclusiva amb altres àmbits/ etiquetes. +issues.label_exclusive_warning = Qualsevol etiqueta amb àmbits conflictius s'esborrarà quan s'editin les etiquetes d'un problema o «pull request». +issues.archived_label_description = (Arxivats) %s +issues.label.filter_sort.reverse_alphabetically = Capgira-ho alfabèticament +issues.label.filter_sort.by_size = Mida més petita +issues.label.filter_sort.reverse_by_size = Mida més gran +issues.num_participants_one = %d participant +issues.num_participants_few = %d participants +issues.tracker = Rastrejador de temps +issues.start_tracking_short = Inicia el temporitzador +issues.start_tracking = Inicia el rastreig de temps +issues.start_tracking_history = `s'ha començat %s` +issues.tracker_auto_close = El temporitzador s'aturarà automàticament quan el problema s'hagi resolt +issues.tracking_already_started = `Ja has començat a rastrejar el temps en un altre problema!` +issues.stop_tracking = Atura el temporitzador +issues.stop_tracking_history = `s'ha aturat %s` +issues.cancel_tracking_history = `s'ha cancel·lat el rastreig de temps %s` +issues.add_time = Afegeix el temps manualment +issues.del_time = Elimina aquest registre de temps +issues.add_time_short = Afegeix temps +issues.add_time_history = `s'ha afegit temps passat %s` +issues.del_time_history = `s'ha eliminat temps passat %s` +issues.add_time_sum_to_small = No s'ha introduït temps. +issues.time_spent_from_all_authors = `Temps total: %s` +issues.due_date = Data de venciment +issues.push_commit_1 = s'ha afegit %d commit %s +issues.push_commits_n = s'ha afegit %d commits %s +issues.force_push_codes = `s'ha forçat la pujada %[1]s des de %[2]s %[8]s a %[4]s %[9]s %[6]s` +issues.due_date_not_set = No s'ha establert una data de venciment. +issues.due_date_added = s'ha afegit la data de venciment %s %s +issues.due_date_modified = s'ha modificat la data de venciment de %[2]s a %[1]s %[3]s +issues.due_date_remove = s'ha eliminat la data de venciment %s %s +issues.due_date_invalid = La data de venciment no és vàlida o és fora de rang. Si us plau, useu el format "aaaa-mm-dd". +issues.dependency.issue_no_dependencies = No s'han establert dependències. +issues.dependency.pr_no_dependencies = No s'ha establert cap dependència. +issues.dependency.no_permission_1 = No teniu permisos per llegir %d dependència +issues.dependency.no_permission_n = No teniu permisos per llegir %d dependències +issues.dependency.no_permission.can_remove = No teniu permisos per llegir aquesta dependència, però la podeu eliminar +issues.dependency.add = Afegir dependència… +issues.dependency.remove_info = Eliminar aquesta dependència +issues.dependency.added_dependency = `s'ha afegit una nova dependència %s` +issues.dependency.removed_dependency = `s'ha eliminat una dependència %s` +issues.dependency.pr_closing_blockedby = No es pot tancar aquesta «pull request» perquè té els següents problemes +issues.dependency.issue_closing_blockedby = No es pot tancar aquest problema perquè té els següents problemes +issues.dependency.issue_close_blocks = Aquest problema bloqueja el tancament d'aquests altres problemes +issues.dependency.pr_close_blocks = Aquesta «pull request» bloqueja el tancament d'aquests problemes +issues.dependency.issue_close_blocked = Heu de tancar tots els problemes que en bloquegen el tancament d'aquest. +issues.dependency.issue_batch_close_blocked = No es poden tancar tots els problemes marcats perquè el problema #%d encara té dependències obertes +issues.dependency.pr_close_blocked = Heu de tancar tots els problemes que bloquegen aquesta «pull request» abans de fusionar-la. +issues.dependency.blocked_by_short = Depèn de +issues.dependency.remove_header = Eliminar dependència +issues.dependency.issue_remove_text = Això eliminarà la dependència d'aquest problema. Continuar? +issues.dependency.pr_remove_text = Això eliminarà la dependència d'aquesta «pull request». Continuar? +issues.dependency.setting = Activa les dependències per a problemes i «pull requests» +issues.dependency.add_error_same_issue = No podeu fer que un problema depengui d'ell mateix. +issues.dependency.add_error_dep_issue_not_exist = El problema que en depèn no existeix. +issues.dependency.add_error_dep_not_exist = La dependència no existeix. +issues.dependency.add_error_dep_exists = La dependència ja existeix. +issues.dependency.add_error_cannot_create_circular = No podeu crear una dependència amb dos problemes que es bloquegen mútuament. +issues.dependency.add_error_dep_not_same_repo = Els dos problemes han d'ésser al mateix repositori. +issues.review.self.approval = No podeu aprovar la vostra «pull request». +issues.review.self.rejection = No podeu sol·licitar canvis en la vostra «pull request». +issues.review.approve = ha aprovat aquests canvis %s +issues.review.comment = ha revisat %s +issues.review.dismissed = ha rebutjat la revisió de %s %s +issues.review.left_comment = ha fet un comentari +issues.review.content.empty = Heu de fer un comentari indicant els canvis que sol·liciteu. +issues.review.reject = canvis sol·licitats %s +issues.review.add_review_request = ha sol·licitat una revisió de %[1]s %[2]s +issues.review.add_review_requests = ha sol·licitat revisions de %[1]s %[2]s +issues.review.remove_review_request = ha eliminat la sol·licitud de revisió per a %[1]s %[2]s +issues.review.remove_review_requests = ha eliminat les sol·licituds de revisió per a %[1]s %[2]s +issues.review.remove_review_request_self = ha rebutjat la revisió %s +issues.review.add_remove_review_requests = ha demanat la revisió a %[1]s i ha eliminat les peticions de revisió a %[2]s %[3]s +issues.review.pending.tooltip = Actualment, la resta d'usuaris no poden veure aquest comentari. Per a publicar els comentaris pendents, selecciona "%s" -> "%s/%s/%s" més amunt. +issues.review.outdated_description = El contingut ha canviat des que es va publicar aquest comentari +issues.review.option.show_outdated_comments = Mostra els comentaris antics +issues.review.option.hide_outdated_comments = Amaga els comentaris antics +issues.review.show_outdated = Mostrar antics +issues.review.hide_outdated = Amagar antics +issues.review.show_resolved = Mostrar resolts +issues.review.hide_resolved = Amagar resolts +issues.review.resolve_conversation = Resol la conversa +issues.review.un_resolve_conversation = Desfés la resolució de la conversa +issues.review.resolved_by = ha marcat aquesta conversa com a resolta +issues.content_history.delete_from_history = Eliminar de la història +issues.content_history.delete_from_history_confirm = Eliminar de la història? +issues.blocked_by_user = No podeu crear problemes en aquest repositori perquè el seu propietari us ha bloquejat. +comment.blocked_by_user = No podeu fer comentaris perquè el propietari o autor del repositori us ha bloquejat. +issues.summary_card_alt = Targeta de resum d'un problema titulat "%s" al repositori %s +pulls.edit.already_changed = No s'han pogut desar els canvis a la «pull request». Sembla que un altre usuari n'ha modificat el contingut. Si us plau, refresqueu la pàgina i intenteu-ho un altre cop per evitar reescriure els seus canvis +pulls.viewed_files_label = s'ha revisat %[1]d / %[2]d fitxers +pulls.filter_branch = Filtra branca +pulls.showing_only_single_commit = Només es mostren els canvis del commit %[1]s +pulls.showing_specified_commit_range = Només es mostren els canvis entre %[1]s..%[2]s +pulls.filter_changes_by_commit = Filtrar per commit +pulls.tab_files = Fitxers modificats +pulls.title_wip_desc = `Comença el títol amb %s per evitar que la «pull request» sigui fusionada accidentalment.` +pulls.still_in_progress = Encara hi treballeu? +pulls.add_prefix = Afegeix el prefix %s +pulls.ready_for_review = A punt per revisar? +pulls.remove_prefix = Elimina el prefix %s +pulls.data_broken = Aquesta «pull request» és malmesa perquè hi falta la informació de la bifurcació. +pulls.required_status_check_failed = Algunes comprovacions no han sigut satisfactòries. +pulls.required_status_check_missing = Falten algunes comprovacions. +pulls.wrong_commit_id = L'ID del commit ha d'ésser a la branca objectiu +pulls.rebase_merge_pull_request = Canvia de base i avança ràpid +pulls.rebase_merge_commit_pull_request = Fes «rebase» i després el commit de fusió +pulls.squash_merge_pull_request = Fes un «squash commit» +pulls.fast_forward_only_merge_pull_request = Només avança ràpid +pulls.rebase_conflict = La fusió ha fallat: Hi ha hagut un conflicte mentre es feia el «rebase» del commit: %[1]s. Consell: Intenteu una altra estratègia +pulls.unrelated_histories = La fusió ha fallat: El cap (head) de la fusió i la base no tenen una història comú. Consell: Intenteu una altra estratègia +pulls.merge_out_of_date = La fusió ha fallat: La base s'ha actualitzat mentre es generava la fusió. Consell: Torneu-ho a intentar. +pulls.head_out_of_date = La fusió ha fallat: El cap (head) s'ha actualitzat mentre es generava la fusió. Consell: Torneu-ho a intentar. +pulls.has_merged = Fallit: La «pull request» ja s'ha fusionat, no podeu fusionar-la de nou ni canviar la branca objectiu. +pulls.push_rejected = La pujada ha fallat: La pujada (push) s'ha rebutjat. Revisa els ganxos Git d'aquest repositori. +pulls.push_rejected_summary = Missatge complet del rebuig +pulls.push_rejected_no_message = La pujada ha fallat: La pujada (push) s'ha rebutjat però no hi havia un missatge remot. Revisa els ganxos Git d'aquest repositori +pulls.open_unmerged_pull_exists = `No podeu reobrir perquè hi ha una «pull request» pendent (#%d) amb les mateixes característiques.` +pulls.status_checking = Hi ha algunes comprovacions pendents +pulls.status_checks_success = Totes les comprovacions s'han resolt +pulls.status_checks_warning = Algunes comprovacions tenen advertències +pulls.status_checks_failure = Algunes comprovacions han fallat +pulls.status_checks_error = Algunes comprovacions han donat errors +pulls.status_checks_hide_all = Amaga totes les comprovacions +pulls.status_checks_show_all = Mostra totes les comprovacions +pulls.update_branch = Actualitza la branca fusionant +pulls.update_branch_rebase = Actualitza la branca fent «rebase» +pulls.update_branch_success = S'ha actualitzat la branca correctament +pulls.update_not_allowed = No teniu permisos per actualitzar la branca +pulls.outdated_with_base_branch = Aquesta branca està desactualitzada amb la branca base +pulls.close = Tancar «pull request» +pulls.closed_at = `ha tancat aquesta «pull request» %s` +pulls.reopened_at = `ha reobert aquesta «pull request» %s` +pulls.commit_ref_at = `ha fet referència a aquesta «pull request» des d'un commit %s` +pulls.cmd_instruction_hint = Veure les instruccions de la línia de comandes +pulls.cmd_instruction_checkout_title = Canviar branca +pulls.cmd_instruction_checkout_desc = Des del repositori del vostre projecte, canvia a una nova branca i comprova els canvis. +pulls.cmd_instruction_merge_desc = Fusionar els canvis i actualitzar-los a Forgejo. +pulls.cmd_instruction_merge_warning = Atenció: La configuració de "Detecta automàticament la fusió manual" no està activa en aquest repositori, haureu de marcar després aquesta «pull request» com a fusionada manualment. +pulls.clear_merge_message = Neteja el missatge de fusió +pulls.clear_merge_message_hint = Netejar el missatge de fusió només esborrarà el contingut del missatge de commit i mantindrà la firma generada de git com "Co-Authored-By …". +pulls.reopen_failed.head_branch = La «pull request» no es pot reobrir perquè el cap (head) de la branca ja no existeix. +pulls.reopen_failed.base_branch = La «pull request» no es pot reobrir perquè la base de la branca ja no existeix. +pulls.agit_explanation = Creat amb el flux de treball d'AGit. L'AGit permet que els contribuents proposin canvis amb "git push" sense crear una bifurcació o branca. +pulls.editable = Editable +pulls.editable_explanation = Els mantenidors poden editar aquesta «pull request». Podeu editar-la directament. +pulls.auto_merge_button_when_succeed = (Quan les comprovacions siguin satisfactòries) +pulls.auto_merge_when_succeed = Fusiona automàticament quan totes les comprovacions siguin satisfactòries +pulls.auto_merge_newly_scheduled = S'ha programat la «pull request» per a ser fusionada quan totes les comprovacions siguin satisfactòries. +pulls.auto_merge_has_pending_schedule = %[1]s ha programat aquesta «pull request» per a ser fusionada quan totes les comprovacions siguin satisfactòries %[2]s. +pulls.auto_merge_cancel_schedule = Cancel·la la fusió automàtica +pulls.auto_merge_not_scheduled = Aquesta «pull request» no es fusionarà automàticament. +pulls.auto_merge_canceled_schedule = S'ha cancel·lat la fusió automàtica per a aquesta «pull request». +pulls.auto_merge_newly_scheduled_comment = `ha programat aquesta «pull request» per a ser fusionada quan totes les comprovacions siguin satisfactòries. %[1]s` +pulls.auto_merge_canceled_schedule_comment = `ha cancel·lat la fusió automàtica d'aquesta «pull request» quan totes les comprovacions siguin satisfactòries %[1]s` +pulls.delete_after_merge.head_branch.is_default = La branca cap (head) que voleu eliminar és la branca predeterminada i no es pot eliminar. +pulls.delete_after_merge.head_branch.is_protected = La branca cap (head) que voleu eliminar està protegida i no es pot eliminar. +pulls.delete_after_merge.head_branch.insufficient_branch = No teniu permisos per eliminar la branca cap (head). +pulls.delete.title = Eliminar aquesta «pull request»? +pulls.delete.text = Realment voleu eliminar aquesta «pull request»? (Això eliminarà permanentment tot el contingut. Considereu millor tancar-la, si la voleu arxivar) +pulls.recently_pushed_new_branches = Heu pujat a la branca %[1]s %[2]s +comments.edit.already_changed = No s'han pogut desar els canvis al comentari. Sembla que un altre usuari n'ha modificat el contingut. Si us plau, refresqueu la pàgina i intenteu-ho un altre cop per evitar reescriure els seus canvis +milestones.new = Nova fita +milestones.closed = Tancat %s +milestones.update_ago = Actualitzat %s +milestones.no_due_date = Sense data de venciment +milestones.new_subheader = Les fites us poden ajudar a organitzar els problemes i fer-ne el seguiment. +milestones.completeness = %d%% Completat +milestones.create = Crear fita +milestones.due_date = Data de venciment (opcional) +milestones.invalid_due_date_format = El format de la data de venciment ha de ser "aaaa-mm-dd". +milestones.create_success = S'ha creat la fita "%s". +milestones.edit = Editar fita +milestones.edit_subheader = Les fites organitzen els problemes i en fan el seguiment. +milestones.modify = Actualitzar fita +milestones.edit_success = S'ha actualitzat la fita "%s". +milestones.deletion = Eliminar fita +milestones.deletion_desc = Eliminar una fita n'esborra tots els problemes. Continuar? +milestones.deletion_success = S'ha eliminat la fita. +milestones.filter_sort.name = Nom +milestones.filter_sort.earliest_due_data = A prop de la data de venciment +milestones.filter_sort.latest_due_date = Lluny de la data de venciment +milestones.filter_sort.least_complete = Menys completa +milestones.filter_sort.most_complete = Més completa +diff.git-notes = Notes +diff.git-notes.add = Afegir nota +diff.git-notes.remove-header = Eliminar nota +diff.git-notes.remove-body = Aquesta nota no s'eliminarà. +diff.data_not_available = El contingut del diff no és disponible +diff.options_button = Opcions del diff +diff.download_patch = Baixa el fitxer pedaç +diff.download_diff = Baixa el fitxer de diff +diff.show_split_view = Vista dividida +diff.show_unified_view = Vista única +diff.whitespace_show_everything = Mostrar tots els canvis +diff.whitespace_ignore_all_whitespace = Ignora els espais en blanc quan es comparin línies +diff.whitespace_ignore_amount_changes = Ignora els canvis en el nombre d'espais en blanc +diff.whitespace_ignore_at_eol = Ignorar els canvis en els espais en blanc al final de la línia +diff.stats_desc = %d fitxers modificats amb %d afegits i %d supressions +diff.stats_desc_file = %d canvis: %d afegits i %d supressions +diff.bin_not_shown = No es mostra el fitxer binari. +diff.view_file = Visualitza el fitxer +diff.file_suppressed = S'ha suprimit el fitxer diff perquè és massa gran +diff.file_suppressed_line_too_long = S'ha suprimit el fitxer de diff perquè una o més línies són massa llargues +diff.too_many_files = Alguns fitxers no es mostren perquè hi ha massa modificacions de fitxers en aquest diff +diff.show_more = Mostra'n més +diff.load = Carrega el diff +diff.generated = generat +diff.comment.add_line_comment = Afegeix un comentari de línia +diff.comment.placeholder = Fes un comentari +diff.comment.add_single_comment = Afegeix només un comentari +diff.comment.add_review_comment = Afegeix un comentari +diff.comment.start_review = Comença la revisió +diff.comment.reply = Respon +diff.review = Acaba la revisió +diff.review.header = Lliura la revisió +diff.review.placeholder = Revisa el comentari +diff.review.comment = Comentari +diff.review.approve = Aprova +diff.review.self_reject = Els autors de la «pull request» no en poden demanar canvis +diff.review.reject = Demana canvis +diff.review.self_approve = Els autors de la «pull request» no la poden aprovar +diff.committed_by = comès per +diff.protected = Protegit +diff.image.side_by_side = L'un vora l'altre +diff.image.swipe = Llisca +diff.image.overlay = Sobreposa +diff.show_file_tree = Mostra l'arbre de fitxers +diff.hide_file_tree = Amaga l'arbre de fitxers +release.releases = Publicacions +release.detail = Detalls de la publicació +release.tags = Etiquetes +release.new_release = Nova publicació +release.draft = Esborrany +release.prerelease = Pre-publicació +release.stable = Estable +release.compare = Compara +release.edit = Edita +release.ahead.commits = %d commits +release.ahead.target = a %s des d'aquesta publicació +release.source_code = Codi font +release.new_subheader = Les publicacions organitzen les versions del projecte. +release.edit_subheader = Les publicacions organitzen les versions del projecte. +release.tag_name = Nom de l'etiqueta +release.target = Objectiu +release.tag_helper = Escull una etiqueta preexistent o crea'n una. +release.tag_helper_new = Nova etiqueta. Aquesta etiqueta es crearà des de l'objectiu. +release.tag_helper_existing = Etiqueta preexistent. +release.title = Nom de publicació +release.title_empty = El títol no pot ser buit. +release.message = Descriu aquesta publicació +release.prerelease_desc = Marca-ho com a pre-publicació +release.prerelease_helper = Marca aquesta publicació com a inadequada en producció. +release.cancel = Cancel·la +release.publish = Publica la publicació +release.save_draft = Desa un esborrany +release.edit_release = Actualitza la publicació +release.delete_release = Elimina la publicació +release.delete_tag = Elimina l'etiqueta +release.deletion = Elimina la publicació +release.deletion_desc = Eliminar una publicació només l'esborra de Forgejo. Això no afectarà l'etiqueta Git, el contingut del vostre repositori o la seva història. Continuar? +release.deletion_success = La publicació s'ha suprimit. +release.deletion_tag_desc = S'esborrarà aquesta etiqueta del repositori. El contingut del repositori i la seva història no es modificaran. Continuar? +release.deletion_tag_success = L'etiqueta s'ha eliminat. +release.tag_name_already_exist = Ja hi ha una publicació amb aquest nom d'etiqueta. +release.tag_name_invalid = El nom d'etiqueta no és vàlid. +release.tag_name_protected = El nom d'etiqueta és protegit. +release.downloads = Baixades + +signing.wont_sign.parentsigned = El commit no se signarà perquè el commit pare no està signat. +signing.wont_sign.headsigned = La fusió no se signarà perquè el commit cap (head) no està signat. +wiki.create_first_page = Crea la primera pàgina +wiki.filter_page = Filtrar pàgina +wiki.search = Cercar wiki +activity.navbar.code_frequency = Freqüència del codi +activity.no_git_activity = No hi ha hagut activitat de commits en aquest període. +activity.git_stats_exclude_merges = Excloent les fusions, +activity.git_stats_push_to_branch = a %s i +activity.git_stats_on_default_branch = En %s, +activity.commit = Activitat de commits +settings.federation_following_repos = URLs dels repositoris següents. Separats per ";" i sense espais. +settings.mirror_settings = Emmiralla la configuració +settings.mirror_settings.docs.disabled_push_mirror.instructions = Configureu el projecte per baixar commits, etiquetes i branques automàticament des d'un altre repositori. +settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning = De moment, això només es pot fer en el menú "Nova Migració". Per a més informació, consulteu: +settings.mirror_settings.docs.disabled_push_mirror.info = L'administrador del vostre lloc ha desactivat la pujada de miralls. +settings.mirror_settings.docs.no_new_mirrors = El vostre repositori emmiralla els canvis d'un altre repositori. Si us plau, tingueu en compte que no podeu crear més miralls de moment. +settings.mirror_settings.docs.can_still_use = Malgrat que no podeu modificar o crear nous miralls, encara podeu usar el mirall existent. +settings.mirror_settings.docs.pull_mirror_instructions = Per configurar un mirall de baixada, consulteu: +settings.mirror_settings.docs.more_information_if_disabled = Aquí trobareu més informació sobre els miralls de pujada i baixada: +settings.mirror_settings.docs.doc_link_title = Com emmirallo repositoris? +settings.mirror_settings.docs.doc_link_pull_section = la secció "Baixar des d'un repositori remot" ("Pulling from a remote repository") a la documentació. +settings.mirror_settings.docs.pulling_remote_title = Baixar des d'un repositori remot +settings.mirror_settings.mirrored_repository = Repositori emmirallat +settings.mirror_settings.pushed_repository = Repositori pujat +settings.mirror_settings.direction.pull = Baixar +settings.mirror_settings.push_mirror.none = No s'ha configurat cap mirall de pujada +settings.mirror_settings.push_mirror.remote_url = URL del repositori Git remot +settings.mirror_settings.push_mirror.add = Afegir un mirall de pujada +settings.mirror_settings.push_mirror.edit_sync_time = Editar l'interval de sincronització del mirall +settings.mirror_settings.push_mirror.none_ssh = Cap +settings.units.add_more = Activa més +settings.pull_mirror_sync_in_progress = Baixant canvis del remot %s. +settings.pull_mirror_sync_quota_exceeded = S'ha superat la quota. No es baixen els canvis. +settings.push_mirror_sync_in_progress = Pujant canvis al remot %s. +settings.update_settings = Desar configuració +settings.update_mirror_settings = Actualitzar la configuració del mirall +settings.branches.add_new_rule = Afegir una nova regla +settings.wiki_desc = Activar la wiki del repositori +settings.wiki_globally_editable = Permet a tothom editar la wiki +settings.use_internal_wiki = Usar la wiki pròpia +settings.use_external_wiki = Usar una wiki externa +settings.external_wiki_url = URL de la wiki externa +settings.external_wiki_url_error = L'URL de la wiki externa no és vàlida. +settings.external_wiki_url_desc = Els visitants es redirigiran a l'URL de la wiki externa quan facin clic a la pestanya wiki. +settings.enable_timetracker = Habilita el seguiment de temps +settings.pulls_desc = Activa les «pull requests» del repositori +settings.pulls.enable_autodetect_manual_merge = Activar la detecció automàtica de les fusions manuals (Nota: En alguns casos, la detecció es pot equivocar) +settings.projects_desc = Activar els projectes del repositori +settings.actions_desc = Activar la «pipeline» CI/CD integrada amb Forgejo Actions +settings.admin_enable_health_check = Activar les comprovacions de salut del repositori (git fsck) +settings.reindex_button = Afegir per reindexar la cua +settings.convert_desc = Podeu convertir aquest mirall en un repositori normal. Aquesta acció no es pot desfer. +settings.convert_notices_1 = Aquesta operació convertirà el mirall en un repositori normal i no es pot desfer. +settings.convert_succeed = El mirall s'ha convertit en un repositori normal. +settings.convert_fork = Convertir a un repositori normal +settings.convert_fork_desc = Podeu convertir aquesta bifurcació en un repositori normal. Aquesta acció no es pot desfer. +settings.convert_fork_notices_1 = Aquesta operació convertirà la bifurcació en un repositori normal i no es pot desfer. +settings.convert_fork_succeed = La bifurcació s'ha convertit en un repositori normal. +settings.transfer_in_progress = Hi ha una transferència en procés. Si us plau, cancel·leu-la si voleu transferir aquest repositori a un altre usuari. +settings.transfer_quota_exceeded = El nou propietari (%s) ha superat la quota. El repositori no s'ha transferit. +settings.signing_settings = Configuració de la verificació de signatures +settings.trust_model = Model de confiança de signatures +settings.trust_model.default = Model de confiança per defecte +settings.trust_model.default.desc = Usar el model de confiança per defecte del repositori per a aquesta instal·lació. +settings.wiki_rename_branch_main = Normalitzar el nom de branca de la wiki +settings.wiki_rename_branch_main_desc = Reanomena la branca interna de la wiki a "%s". Aquest canvi és permanent i no es pot desfer. +settings.wiki_rename_branch_main_notices_1 = Aquesta operació NO es pot desfer. +settings.wiki_branch_rename_success = El nom de branca de la wiki del repositori s'ha normalitzat correctament. +settings.wiki_branch_rename_failure = No s'ha pogut normalitzar el nom de branca de la wiki del repositori. +settings.confirm_wiki_branch_rename = Reanomenar la branca de la wiki +settings.wiki_delete = Eliminar les dades de la wiki +settings.wiki_delete_desc = Eliminar les dades de la wiki del repositori és una acció permanent i no es pot desfer. +settings.wiki_delete_notices_1 = - Això eliminarà permanentment i desactivarà la wiki del repositori %s. +settings.confirm_wiki_delete = Eliminar les dades de la wiki +settings.wiki_deletion_success = Les dades de la wiki del repositori s'han eliminat. +settings.delete = Eliminar aquest repositori +settings.delete_desc = Eliminar un repositori és permanent i no es pot desfer. +settings.delete_notices_1 = - Aquesta operació NO es pot desfer. +settings.delete_notices_2 = - Aquesta operació eliminarà permanentment el repositori %s, incloent el codi, les incidències, els comentaris, la wiki i les configuracions dels col·laboradors. +settings.delete_notices_fork_1 = - Les bifurcacions d'aquest repositori esdevindran independents després de l'eliminació. +settings.deletion_success = El repositori s'ha eliminat. +settings.update_settings_success = S'ha actualitzat la configuració del repositori. +settings.update_settings_no_unit = El repositori hauria de permetre algun tipus d'interacció. +settings.confirm_delete = Eliminar repositori +settings.add_collaborator = Afegir col·laborador +settings.add_collaborator_success = El col·laborador s'ha afegit. +settings.add_collaborator_inactive_user = No podeu afegir un usuari inactiu com a col·laborador. +settings.add_collaborator_owner = No podeu afegir un propietari com a col·laborador. +settings.add_collaborator_duplicate = Aquesta col·laborador ja està afegit al repositori. +settings.add_collaborator_blocked_our = No podeu afegir aquest col·laborador perquè el propietari del repositori l'ha bloquejat. +settings.add_collaborator_blocked_them = No podeu afegir aquest col·laborador perquè ha bloquejat el propietari del repositori. +settings.collaborator_deletion = Suprimir col·laborador +settings.collaborator_deletion_desc = Suprimir un col·laborador en traurà l'accés al repositori. Continuar? +settings.remove_collaborator_success = El col·laborador s'ha suprimit. +settings.org_not_allowed_to_be_collaborator = No podeu afegir una organització com a col·laborador. +settings.change_team_access_not_allowed = Només el propietari de l'organització pot canviar l'accés d'equip en aquest repositori +settings.team_not_in_organization = L'equip no és en la mateixa organització que el repositori +settings.add_team_duplicate = L'equip ja té el repositori +settings.add_team_success = L'equip ara tindrà accés al repositori. +settings.change_team_permission_tip = Els permisos de l'equip es configuren a la pàgina de l'equip i no es poden canviar individualment per repositori +settings.add_webhook = Afegir webhook +settings.add_webhook.invalid_channel_name = El nom del canal webhook no pot ser buit i no pot contenir només un #. +settings.add_webhook.invalid_path = El camí no pot contenir ".", ".." o una cadena buida. Tampoc pot començar o acabar amb una barra "/". +settings.webhook_deletion = Eliminar webhook +settings.webhook_deletion_desc = Eliminar un webhook n'elimina la configuració i la història de lliurament. Continuar? +settings.webhook_deletion_success = S'ha eliminat el webhook. + +unescape_control_characters = Des-escapar +view_git_blame = Veure git blame +vendored = Proveïdor +editor.propose_file_change = Proposa canvis en el fitxer +editor.invalid_commit_mail = Adreça de correu electrònic incorrecta per crear un commit. +editor.file_changed_while_editing = El contingut del fitxer ha canviat des que el vau obrir. Feu clic aquí per veure'l o feu commit dels canvis un altre cop per sobreescriure'l. +editor.commit_empty_file_text = L'arxiu que s'està a punt de cometre és buit. Procedir? +editor.push_rejected_no_message = El servidor ha rebutjat el canvi sense més detalls. Si us plau, reviseu els ganxos de Git. +editor.push_rejected = El servidor ha rebutjat el canvi. Si us plau, reviseu els ganxos de Git. +editor.cannot_commit_to_protected_branch = No es pot fer commit a la branca protegida "%s". +editor.no_commit_to_branch = No s'ha pogut fer commit directament a la branca perquè: +editor.require_signed_commit = La branca requereix un commit signat +commits.renamed_from = Reanomenat de %s +commits.signed_by_untrusted_user = Signat per un usuari no fiable +projects.edit_subheader = Els projectes organitzen les incidències i fan seguiment del progrés. +issues.choose.invalid_templates = S'han trobat %v plantilles invàlides +pulls.merged_by_fake = per %[2]s ha sigut fusionada %[1]s +issues.commit_ref_at = `ha fet referència a aquesta incidència en un commit %s` +issues.ref_from = `de %[1]s` +issues.unpin_issue = Desfixar la incidència +issues.pin_comment = ha fixat aquest %s +issues.unpin_comment = ha desfixat aquest %s +issues.lock_with_reason = bloquejada com a %s i conversa restringida als col·laboradors %s +issues.lock_no_reason = bloquejada i conversa restringida als col·laboradors %s +issues.lock.reason = Causa del bloqueig +pulls.allow_edits_from_maintainers = Permetre edicions dels mantenidors +pulls.compare_changes_desc = Seleccioneu la branca on fusionar i la branca d'on extreure. +pulls.switch_comparison_type = Intercanvia el tipus de comparació +pulls.switch_head_and_base = Intercanvia el head i la base +pulls.show_all_commits = Mostrar tots els commits +pulls.select_commit_hold_shift_for_range = Seleccioneu el commit. Premeu shift + feu clic per seleccionar un rang +pulls.is_checking = La comprovació de conflictes de fusió està en curs. Proveu de nou d'aquí una estona. +pulls.is_empty = Els canvis en aquesta branca ja són a la branca de destí. Aquest serà un commit buit. +pulls.required_status_check_administrator = Com a administrador, podeu fusionar aquesta «pull request» de totes maneres. +pulls.num_conflicting_files_1 = %s fitxer en conflicte +pulls.num_conflicting_files_n = %s fitxers en conflicte +pulls.reject_count_1 = %d sol·licitud de canvi +pulls.reject_count_n = %s sol·licituds de canvi +pulls.waiting_count_1 = %d revisió en espera +pulls.waiting_count_n = %d revisions en espera +pulls.no_merge_not_ready = Aquesta «pull request» no està llesta per a ser fusionada, comprova l'estat de revisió i les comprovacions d'estat. +pulls.merge_pull_request = Crear un commit de fusió +pulls.merge_commit_id = L'ID del commit de fusió +pulls.require_signed_wont_sign = La branca requereix commits signats, però aquesta fusió no estarà signada +milestones.filter_sort.most_issues = Més incidències +milestones.filter_sort.least_issues = Menys incidències +signing.will_sign = Aquest commit es signarà amb la clau "%s". +signing.wont_sign.error = S'ha produït un error mentre es comprovava si el commit es podia signar. +signing.wont_sign.nokey = Aquesta instància no té cap clau per signar aquest commit. +signing.wont_sign.never = Els commits no es signen mai. +signing.wont_sign.always = Els commits es signen sempre. +signing.wont_sign.pubkey = El commit no es signarà perquè no teniu cap clau pública associada al vostre compte. +signing.wont_sign.twofa = Heu de tenir habilitada l'autenticació de doble factor per tenir commits signats. +signing.wont_sign.basesigned = La fusió no es signarà perquè el commit base no està signat. +signing.wont_sign.commitssigned = La fusió no es signarà perquè cap dels commits associats està signat. +wiki.file_revision = Revisió de la pàgina +wiki.wiki_page_revisions = Revisions de la pàgina +wiki.back_to_wiki = Tornar a la pàgina de la wiki +wiki.reserved_page = El nom de pàgina wiki "%s" està reservat. +wiki.last_updated = Actualitzat per última vegada %s +wiki.page_name_desc = Introduïu un nom per aquesta pàgina de la Wiki. Alguns noms especials són: "Home", "_Sidebar" i "_Footer". +activity.navbar.pulse = Pols +activity.navbar.recent_commits = Commits recents +activity.published_prerelease_label = Pre-publicació +activity.git_stats_commit_1 = %d commit +activity.git_stats_commit_n = %d commits +activity.git_stats_push_to_all_branches = a totes les branques. +settings.githooks = Ganxos de Git +settings.mirror_settings.docs.disabled_pull_mirror.instructions = Configureu el vostre projecte per enviar automàticament commits, etiquetes i branques. L'administrador del vostre lloc ha desactivat els miralls de baixada (pull). +settings.issues_desc = Activar el gestor d'incidències +settings.use_internal_issue_tracker = Usa el gestor d'incidències per defecte +settings.use_external_issue_tracker = Usa un gestor d'incidències extern +settings.external_tracker_url = URL del gestor d'incidències extern +settings.external_tracker_url_error = L'URL del gestor d'incidències extern no és vàlida. +settings.external_tracker_url_desc = Quan els visitants facin clic a la pestanya d'incidències, se'ls redirigirà a l'URL del gestor d'incidències extern. +settings.tracker_url_format = Format de l'URL del gestor d'incidències extern +settings.tracker_url_format_error = El format de l'URL del gestor d'incidències extern no és vàlid. +settings.tracker_issue_style = Format de número del gestor d'incidències extern +settings.tracker_issue_style.regexp_pattern_desc = S'usarà el primer grup capturat enlloc de {index}. +settings.tracker_url_format_desc = Usa els espais reservats {user}, {repo} i {index} com a nom d'usuari, nom de repositori i índex d'incidències. +settings.pulls.allow_rebase_update = Activa canviar la branca dels «pull request» per «rebase» +settings.default_update_style_desc = Mètode predeterminat que s'usarà per actualitzar les «pull requests» darrere de la branca base. +settings.pulls.default_delete_branch_after_merge = Eliminar per defecte la branca dels «pull request» després de fusionar-los +settings.packages_desc = Activar el registre de paquets del repositori +settings.admin_enable_close_issues_via_commit_in_any_branch = Tancar una incidència mitjançant un commit en una branca no principal +settings.trust_model.collaborator.desc = Les signatures vàlides dels col·laboradors d'aquest repositori es marcaran com a "confiables" (coincideixin o no amb l'autor del commit). Altrament, es marcaran com a "no confiables" si la signatura coincideix amb l'autor i com a "no coincidents" si no en coincideixen. +settings.trust_model.committer.long = Autor del commit: Confia les signatures que coincideixen amb els autors dels commits (Aquest és el comportament de GitHub i farà que els commit signats per Forgejo tinguin Forgejo com a autor) +settings.trust_model.committer.desc = Les signatures vàlides només es marcaran com a "confiables" si coincideixen amb l'autor del commit, altrament es marcaran com a "no coincidents". Això força que Forgejo sigui l'autor en els commits signats, amb l'autor real indicat com a Co-authored-by: i Co-committed-by: al final del commit. La clau per defecte de Forgejo ha de coincidir amb un User a la base de dades. +settings.trust_model.collaboratorcommitter.long = Col·laborador+Autor del commit: Confia en les signatures dels col·laboradors que coincideixin amb l'autor del commit +settings.trust_model.collaboratorcommitter.desc = Les signatures vàlides dels col·laboradors es marcaran com a "confiables" si coincideixen amb l'autor del commit. Altrament, es marcaran com a "no confiables" si la signatura coincideix amb l'autor i com a "no coincidents" si no en coincideix. Això força que Forgejo sigui l'autor dels commits signats amb l'autor real indicat amb Co-Authored-By: i Co-Committed-By: al final del commit. La clau per defecte de Forgejo ha de coincidir amb un User a la base de dades. +settings.wiki_rename_branch_main_notices_2 = Això canviarà permanentment el nom de la branca interna de la wiki del repositori %s. S'haurà d'actualitzar els checkouts existents. +settings.hooks_desc = Els webhooks fan consultes HTTP POST al servidor, automàticament, quan es disparen certs esdeveniments de Forgejo. Llegiu-ne més a la guia de webhooks. +settings.webhook.test_delivery = Prova de lliurament +settings.webhook.test_delivery_desc = Prova aquest webhook amb un esdeveniment fals. +settings.webhook.test_delivery_desc_disabled = Activeu primer el webhook per a provar-lo amb un esdeveniment fals. +settings.webhook.request = Consulta +settings.webhook.replay.description = Rellança aquest webhook. +settings.webhook.replay.description_disabled = Activeu el webhook per rellançar-lo. +settings.webhook.delivery.success = S'ha afegit un esdeveniment a la cua de lliurament. Pot trigar uns segons a aparèixer a l'historial de lliurament. +settings.githooks_desc = Git gestiona els ganxos git. Podeu editar els fitxers de ganxo següents per configurar operacions personalitzades. +settings.githook_edit_desc = Si el ganxo és inactiu, es presentarà contingut de mostra. Deixar el contingut buit desactivarà aquest ganxo. +settings.githook_name = Nom del ganxo +settings.githook_content = Contingut del ganxo +settings.update_githook = Actualitzar ganxo +settings.add_webhook_desc = Forgejo enviarà consultes POST amb un Content-Type especificat a l'URL de destí. Llegiu-ne més a la guia de webhooks. +settings.payload_url = URL de destí +settings.http_method = Mètode HTTP +settings.content_type = Tipus de contingut POST +settings.slack_icon_url = URL de la icona +settings.discord_icon_url = URL de la icona +settings.discord_icon_url.exceeds_max_length = L'URL de la icona ha de ser menor o igual a 2048 caràcters +settings.event_desc = Dispara quan: +settings.event_push_only = Pujades (push) +settings.event_choose = Esdeveniments personalitzats… +settings.event_header_repository = Esdeveniment de repositori +settings.event_create_desc = es creï una branca o etiqueta. +settings.event_delete_desc = s'elimini una branca o etiqueta. +settings.event_fork_desc = es bifurqui el repositori. +settings.event_wiki_desc = es creï, modifiqui o elimini una pàgina de la wiki. +settings.event_push_desc = es pugi (push) al repositori. +settings.event_repository_desc = es creï o elimini un repositori. +settings.event_header_issue = Esdeveniments d'incidències +settings.event_issues_desc = s'obri, tanqui o editi una incidència. +settings.event_issue_assign_desc = es canviï l'assignació d'una incidència. +settings.event_issue_label_desc = s'afegeixi o esborri una etiqueta d'incidència. +settings.event_issue_comment_desc = es creï, editi o elimini un comentari d'incidència. +settings.event_header_pull_request = Esdeveniments de «pull request» +settings.event_pull_request_desc = s'obri, tanqui o editi una «pull request». +settings.event_pull_request_assign_desc = es canviï l'assignació d'una «pull request». +settings.event_pull_request_label_desc = s'afegeixi o esborri una etiqueta de «pull request». +settings.event_pull_request_comment_desc = es creï, editi o elimini un comentari de «pull request». +settings.event_pull_request_review_desc = s'aprovi o rebutgi una «pull request» o se n'afegeixin comentaris de revisió. +settings.event_pull_request_sync_desc = es canviï la branca automàticament a la branca objectiu. +settings.event_pull_request_review_request = se sol·liciti revisió +settings.event_pull_request_review_request_desc = se sol·licitin revisions a la «pull request» o se n'elimini la sol·licitud. +settings.event_pull_request_approvals = s'accepti una «pull request» +settings.event_pull_request_merge = es fusioni una «pull request» +settings.event_header_action = Esdeveniments d'execució d'accions +settings.event_action_failure = Fallada +settings.event_action_failure_desc = L'Acció ha fallat. +settings.event_action_recover_desc = La execució de l'acció ha finalitzat amb èxit després de que la última execució en el mateix flux fallés. +settings.event_action_success_desc = La execució de l'acció ha tingut èxit. +settings.event_package_desc = Paquet creat o eliminat en un repositori. +settings.branch_filter = Filtre de branca +settings.branch_filter_desc = Llista blanca de la branca per als esdeveniments de pujada i creació/eliminació de branques, especificada com un patró «glob». Si és buida o *, s'enregistraran els esdeveniments de totes les branques. Vegeu la documentació %[2]s per a la sintaxi. Per exemple: master, {master,release*}. +settings.authorization_header = Capçalera d'Autorització +settings.authorization_header_desc = S'inclourà com a capçalera d'autorització per a les «requests» quan hi sigui. Exemples: %s. +settings.active_helper = La informació sobre els esdeveniments disparats s'enviarà a aquesta URL webhook. +settings.add_hook_success = S'ha afegit el webhook. +settings.update_webhook = Actualitzar webhook +settings.update_hook_success = S'ha actualitzat el webhook. +settings.delete_webhook = Eliminar webhook +settings.recent_deliveries = Lliuraments recents +settings.hook_type = Tipus de ganxo +settings.add_web_hook_desc = Integrar %s al vostre repositori. +settings.graphql_url = URL GraphQL +settings.web_hook_name_feishu = Feishu / Lark Suite +settings.web_hook_name_larksuite_only = Lark Suite +settings.web_hook_name_wechatwork = WeCom (Wechat Work) +settings.packagist_username = Nom d'usuari Packagist +settings.packagist_api_token = Testimoni API +settings.packagist_package_url = URL del paquet Packagist +settings.web_hook_name_sourcehut_builds = Builds SourceHut +settings.sourcehut_builds.manifest_path = Camí del build manifest +settings.sourcehut_builds.visibility = Visibilitat del treball +settings.sourcehut_builds.secrets_helper = Permet que el treball accedeixi als secrets de build (necessita el permís SECRETS:RO) +settings.sourcehut_builds.access_token_helper = Testimoni d'accés que té el permís JOBS:RW. Genera un testimoni builds.sr.ht o un testimoni builds.sr.ht amb accés a secrets a meta.sr.ht. +settings.deploy_keys = Clau d'implementació +settings.add_deploy_key = Afegir clau d'implementació +settings.deploy_key_desc = Les claus d'implementació poden tenir accés només-de-lectura o de lectura-i-escriptura al repositori. +settings.is_writable = Activa l'accés d'escriptura +settings.is_writable_info = Permeteu que aquesta clau d'implementació pugui pujar (push) al repositori. +settings.no_deploy_keys = Encara no hi ha claus d'implementació. +settings.key_been_used = Ja hi ha una clau d'implementació idèntica. +settings.key_name_used = Ja hi ha una clau d'implementació amb el mateix nom. +settings.add_key_success = S'ha afegit la clau d'implementació "%s". +settings.deploy_key_deletion = Eliminar clau d'implementació +settings.deploy_key_deletion_desc = Eliminar una clau d'implementació en traurà l'accés al repositori. Continua? +settings.deploy_key_deletion_success = S'ha eliminat la clau d'implementació. +settings.protected_branch.save_rule = Regle de desada +settings.protected_branch.delete_rule = Regla d'eliminada +settings.branch_protection = Regles de protecció per a la branca "%s" +settings.protect_new_rule = Crear una nova regla de protecció de branca +settings.protect_disable_push = Desactivar pujada +settings.protect_disable_push_desc = No es permetrà la pujada (push) en aquesta branca. +settings.protect_enable_push = Activar pujada +settings.protect_enable_push_desc = Tothom que tingui accés d'escriptura podrà pujar (push) a la branca (però no «force push»). +settings.protect_enable_merge = Activar fusió +settings.protect_enable_merge_desc = Tothom amb accés d'escriptura podrà fusionar «pull requests» a la branca. +settings.protect_whitelist_committers = Pujada restringida +settings.protect_whitelist_committers_desc = Només els usuaris i equips indicats a la llista blanca podran pujar (push) a la branca (però no «force push»). +settings.protect_whitelist_deploy_keys = Posar les claus d'implementació amb accés d'escriptura per pujar (push) a la llista blanca. +settings.protect_whitelist_users = Llista blanca d'usuaris per pujar +settings.protect_whitelist_teams = Llista blanca d'equips per pujar +settings.protect_merge_whitelist_committers = Activar llista blanca de fusió +settings.protect_merge_whitelist_committers_desc = Només els usuaris i equips indicats a la llista blanca podran fusionar «pull requests» a la branca. +settings.protect_merge_whitelist_users = Llista blanca d'usuaris per fusionar +settings.protect_merge_whitelist_teams = Llista blanca d'equips per fusionar +settings.protect_status_check_patterns = Patrons de comprovació d'estat +settings.protect_status_check_patterns_desc = Introdueix patrons per especificar quines comprovacions s'han de fer abans de que una branca es pugui fusionar en aquesta branca. Cada línia especifica un patró. Els patrons no poden estar buits. +settings.protect_check_status_contexts_desc = Requerir comprovació d'estat abans de fusionar. Quan s'activa, els commits s'han de pujar primer en una altra branca, i llavors es podran fusionar o pujar directament a la branca que indica aquesta regla, un cop hagin passat les comprovacions. Si no s'indica cap context, l'últim commit ha de ser satisfactori, sigui quin sigui el context. +settings.protect_check_status_contexts_list = Comprovacions d'estat de la darrera setmana d'aquest repositori +settings.protect_invalid_status_check_pattern = Patró de comprovació invàlid: "%s". +settings.protect_no_valid_status_check_patterns = Sense patrons de comprovació d'estat vàlids. +settings.protect_required_approvals = Aprovacions necessàries +settings.protect_required_approvals_desc = Permet fusionar només «pull requests» amb prou revisions positives. +settings.protect_approvals_whitelist_enabled = Limita les aprovacions als usuaris o equips de la llista blanca +settings.protect_approvals_whitelist_enabled_desc = Només comptaran cap al total d'aprovacions necessàries les revisions d'usuaris i equips de la llista blanca. Si la llista és buida, en comptaran les revisions de tothom amb accés d'escriptura. +settings.protect_approvals_whitelist_users = Revisors en la llista blanca +settings.protect_approvals_whitelist_teams = Equips en la llista blanca per revisions +settings.dismiss_stale_approvals = Ignora les aprovacions estancades +settings.dismiss_stale_approvals_desc = Quan es facin commits nous a la branca que canviïn el contingut de la «pull request», les aprovacions antigues es descartaran. +settings.ignore_stale_approvals = Ignorar aprovacions estancades +settings.ignore_stale_approvals_desc = No afegeix el nombre d'aprovacions fetes en commits antics (revisions estancades) al total d'aprovacions de la PR. Això és irrellevant si les revisions estancades ja es descarten. +settings.require_signed_commits = Requerir commits signats +settings.require_signed_commits_desc = Rebutja pujades a aquesta branca si no són signades o no es poden verificar. +settings.protect_branch_name_pattern = Patró de nom de branca protegit +settings.protect_branch_name_pattern_desc = Patrons de nom de branca protegits. Vegeu la documentació per la sintaxi de patrons. Per exemple: main, release/** +settings.protect_protected_file_patterns = Patrons de fitxer protegits (separats amb punt i coma ";") +settings.protect_protected_file_patterns_desc = Els fitxers protegits no es poden modificar directament encara que l'usuari tingui permisos per afegir, editar i eliminar fitxers en aquesta branca. Es pot indicar més d'un patró, separats amb punt i coma (";"). Vegeu la documentació %[2]s per la sintaxi de patrons. Per exemple: .drone.yml, /docs/**/*.txt. +settings.protect_unprotected_file_patterns = Patrons de fitxer no protegits (separats amb punt i coma ";") +settings.protect_unprotected_file_patterns_desc = Els usuaris amb accés d'escriptura poden modificar els fitxers no protegits, saltant-se la restricció de pujada. Es pot indicar més d'un patró, separats amb punt i coma (";"). Vegeu la documentació %[2]s per la sintaxi de patró. Per exemple: .drone.yml, /docs/**/*.txt. +settings.update_protect_branch_success = La regla de protecció de branca "%s" s'ha actualitzat. +settings.remove_protected_branch_success = La regla de protecció de branca "%s" s'ha eliminat. +settings.remove_protected_branch_failed = No s'ha pogut eliminar la regla de protecció de branca "%s". +settings.protected_branch_deletion = Protecció d'eliminació de branca +settings.protected_branch_deletion_desc = Desactivar la protecció de branca permet als usuaris amb accés d'escriptura pujar a la branca. Continua? +settings.block_rejected_reviews = Bloqueja la fusió en revisions rebutjades +settings.block_rejected_reviews_desc = No es podrà fusionar quan els revisors oficials en sol·licitin canvis, encara que hi hagi prou aprovacions. +settings.block_on_official_review_requests = Bloquejar fusió en sol·licituds de revisió oficials +settings.block_on_official_review_requests_desc = No es podrà fusionar quan tingui sol·licituds de revisió oficials, encara que hi hagi prou aprovacions. +settings.block_outdated_branch = Bloquejar fusió si la «pull request» és obsoleta +settings.block_outdated_branch_desc = No es podrà fusionar quan la branca cap (head) sigui darrera la branca base. +settings.enforce_on_admins = Aplica aquesta regla als administradors del repositori +settings.enforce_on_admins_desc = Els repositoris del repositori no poden saltar-se aquesta regla. +settings.default_branch_desc = Tria una branca per defecte del repositori per a «pull requests» i commits: +settings.merge_style_desc = Estils de fusió +settings.default_merge_style_desc = Estil de fusió predeterminat +settings.choose_branch = Tria una branca… +settings.no_protected_branch = No hi ha branques protegides. +settings.protected_branch_required_rule_name = Nom de regla obligatori +settings.protected_branch_duplicate_rule_name = Ja hi ha una regla per a aquest set de branques +settings.protected_branch_required_approvals_min = El nombre d'aprovacions necessàries no pot ser negatiu. +settings.tags.protection = Protecció d'etiquetes +settings.tags.protection.pattern = Patró d'etiquetes +settings.tags.protection.allowed.users = Usuaris permesos +settings.tags.protection.allowed.teams = Equips permesos +settings.tags.protection.allowed.noone = Ningú +settings.tags.protection.create = Afegir regla +settings.tags.protection.none = No hi ha etiquetes protegides. +settings.tags.protection.pattern.description = Podeu usar un sol nom o un patró «glob» o expressió regular per coincidir amb diferents etiquetes. Llegiu-ne més en la guia d'etiquetes protegides. +settings.bot_token = Testimoni de bot +settings.chat_id = ID de Xat +settings.thread_id = ID de fil +settings.matrix.homeserver_url = URL del homeserver +settings.matrix.room_id = ID de sala +settings.matrix.message_type = Tipus de missatge +settings.archive.text = Arxivar el repositori el farà de només-lectura. S'amagarà del tauler. Ningú (tampoc vós!) hi podrà fer commits nous, o obrir-hi incidències o «pull requests». +settings.archive.error = Hi ha hagut un error en arxivar el repositori. Vegeu el log per més detalls. +settings.archive.error_ismirror = No podeu arxivar un repositori mirall. +settings.archive.branchsettings_unavailable = La configuració de branca no és disponible en repositoris arxivats. +settings.archive.tagsettings_unavailable = La configuració d'etiquetes no és disponible en repositoris arxivats. +settings.archive.mirrors_unavailable = Els miralls no són disponibles en repositoris arxivats. +settings.unarchive.button = Des-arxivar repositori +settings.unarchive.header = Des-arxiva aquest repositori +settings.unarchive.text = Des-arxivar el repositori farà possible rebre-hi commits i pujades, així com noves incidències i «pull requests». +settings.unarchive.success = El repositori s'ha des-arxivat satisfactòriament. +settings.unarchive.error = Hi ha hagut un error en des-arxivar el repositori. Vegeu el log per més detalls. +settings.update_avatar_success = S'ha actualitzat l'avatar del repositori. +settings.lfs_filelist = Fitxers LFS desats en aquest repositori +settings.lfs_no_lfs_files = No hi ha fitxers LFS desats en aquest repositori +settings.lfs_findcommits = Cercar commits +settings.lfs_lfs_file_no_commits = No s'ha trobat commits en aquest fitxer LFS +settings.lfs_noattribute = Aquest camí no té l'atribut bloquejable en la branca per defecte +settings.lfs_delete = Eliminar fitxer LFS amb OID %s +settings.lfs_delete_warning = Eliminar un fitxer LFS pot provocar errors de "aquest objecte no existeix" en fer checkout. Continuar? +settings.lfs_findpointerfiles = Cercar fitxers de punters +settings.lfs_locks = Bloqueigs +settings.lfs_invalid_locking_path = Camí invàlid: %s +settings.lfs_invalid_lock_directory = No es pot bloquejar el directori: %s +settings.lfs_lock_already_exists = Ja està bloquejat: %s +settings.lfs_lock = Bloqueig +settings.lfs_lock_path = Camí al fitxer per bloquejar… +settings.lfs_locks_no_locks = Sense bloqueigs +settings.lfs_lock_file_no_exist = El fitxer bloquejat no existeix en la branca per defecte +settings.lfs_force_unlock = Forçar el desbloqueig +settings.lfs_pointers.found = S'ha trobat %d punters de blob - %d associats, %d no associats (%d no són a l'emmagatzematge) +settings.lfs_pointers.sha = Hash del «blob» +settings.lfs_pointers.inRepo = En repositori +settings.lfs_pointers.exists = Existeix en magatzem +settings.lfs_pointers.accessible = Accessible per l'usuari +settings.lfs_pointers.associateAccessible = Associar %d OIDs accessibles +settings.rename_branch_failed_protected = No es pot canviar el nom de la branca %s perquè està protegida. +settings.rename_branch_failed_exist = No es pot canviar el nom de la branca perquè la branca objectiu %s existeix. +settings.rename_branch_failed_not_exist = No es pot canviar el nom de la branca %s perquè no existeix. +settings.rename_branch_success = S'ha canviat el nom de la branca %s satisfactòriament. +settings.rename_branch = Canviar el nom de branca +diff.browse_source = Explorar codi font +diff.comment.markdown_info = S'admet el format Markdown. +release.add_tag_msg = Usar el títol i contingut de la publicació com al missatge d'etiqueta. +release.hide_archive_links = Amagar els arxius generats automàticament +release.hide_archive_links_helper = Amaga automàticament els arxius de codi font generats per a aquesta publicació. Per exemple, si n'esteu pujant els vostres. +release.add_tag = Crear etiqueta +release.releases_for = Publicacions per %s +release.tags_for = Etiquetes per %s +release.system_generated = Aquest adjunt es genera automàticament. +release.type_attachment = Adjunt +release.type_external_asset = Actiu extern +release.asset_name = Nom d'actiu +release.asset_external_url = URL externa +release.add_external_asset = Afegeix actiu extern +release.invalid_external_url = URL externa invàlida: "%s" +release.summary_card_alt = Panell de resum d'una publicació titulada "%s" al repositori %s +branch.name = Nom de branca +branch.already_exists = Ja existeix una branca anomenada "%s". +branch.delete = Eliminar branca "%s" +branch.delete_html = Eliminar branca +branch.delete_desc = Eliminar una branca és permanent. Malgrat la branca eliminada pot seguir existint durant una estona abans d'eliminar-se completament, aquesta acció NO es pot desfer en la majoria de casos. Continuar? +branch.deletion_success = S'ha eliminat la branca "%s". +branch.deletion_failed = No s'ha pogut eliminar la branca "%s". +branch.delete_branch_has_new_commits = No s'ha pogut eliminar la branca "%s" perquè s'han afegit nou commits després de fusionar-la. +branch.create_branch = Crear branca %s +branch.create_from = des de "%s" +branch.create_success = S'ha creat la branca "%s". +branch.branch_already_exists = La branca "%s" ja existeix en aquest repositori. +branch.branch_name_conflict = El nom de branca "%s" col·lideix amb la branca "%s" que ja existeix. +branch.tag_collision = No es pot crear la branca "%s" perquè ja existeix una etiqueta amb el mateix nom al repositori. +branch.deleted_by = Eliminada per %s +branch.restore_success = S'ha restaurat la branca "%s". +branch.restore_failed = No s'ha pogut restaurar la branca "%s". +branch.protected_deletion_failed = La branca "%s" és protegida. No es pot eliminar. +branch.default_deletion_failed = La branca "%s" és la branca per defecte. No es pot eliminar. +branch.restore = Restaurar la branca "%s" +branch.download = Baixar la branca "%s" +branch.rename = Canviar el nom de la branca "%s" +branch.included_desc = Aquesta branca és part de la branca per defecte +branch.included = Inclosa +branch.create_new_branch = Crear branca des de branca: +branch.confirm_create_branch = Crear branca +branch.warning_rename_default_branch = Esteu canviant el nom de la branca per defecte. +branch.rename_branch_to = Canviant el nom de la branca "%s". +branch.create_branch_operation = Crear branca +branch.new_branch = Crear branca nova +branch.new_branch_from = Crear branca nova des de "%s" +branch.renamed = La branca %s ha canviat el nom a %s. +tag.create_tag = Crear etiqueta %s +tag.create_tag_operation = Crear etiqueta +tag.confirm_create_tag = Crear etiqueta +tag.create_tag_from = Crear nova etiqueta des de "%s" +tag.create_success = S'ha creat l'etiqueta "%s". +topic.manage_topics = Gestionar temes +topic.count_prompt = No podeu seleccionar més de 25 temes +topic.format_prompt = Els temes han de començar amb una lletra o número, poden incloure guions ("-") i punts ("."), i tenir fins a 35 caràcters. Les lletres han de ser minúscules. +find_file.go_to_file = Cercar fitxer +find_file.no_matching = No s'ha trobat un fitxer coincident +error.csv.too_large = No es pot mostrar aquest fitxer perquè és massa gran. +error.csv.unexpected = No es pot mostrar aquest fitxer perquè conté un caràcter inesperat a la línia %d i columna %d. +error.csv.invalid_field_count = No es pot mostrar aquest fitxer perquè té un nombre d'entrades incorrecte a la línia %d. + +settings.matrix.access_token_helper = Es recomana muntar un compte de Matrix dedicat per això. El testimoni d'accés el podeu trobar al client web Element (en una pestanya privada/d'incògnit) > User menu (cantó superior esquerre) > All settings > Help & About > Advanced > Access Token (sota de l'URL del homeserver). Tanqueu la pestanya privada/d'incògnit (tancar la sessió invalidaria el testimoni). +settings.matrix.room_id_helper = L'ID de sala el podeu trobar al client web Element > Room Settings > Advanced > Internal room ID. Per exemple: %s. + +diff.parent = pare [user] unblock = Desbloquejar @@ -1601,14 +2667,22 @@ public_activity.visibility_hint.self_private_profile = La vostra activitat és v change_avatar = Canvieu el vostre avatar… joined_on = S'ha unit el %s +starred = Repositoris destacats + [git.filemode] executable_file = Fitxer executable symbolic_link = Enllaç simbòlic submodule = Submòdul +directory = Directori +normal_file = Fitxer normal + [markup] filepreview.truncated = La vista prèvia s'ha truncat +filepreview.line = Línia %[1]d a %[2]s +filepreview.lines = Línies %[1]d a %[2]d en %[3]s + [translation_meta] test = Aquest és un text de prova. No es mostra a l'interfície d'usuari de Forgejo, però s'utilitza amb finalitats de prova. Pots introduir "d'acord" per a estalviar temps (o alguna frase divertida al teu gust) i arribar a la dolça fita del 100% :) @@ -1636,7 +2710,7 @@ settings.confirm_delete_account = Confirmar-ne l'eliminació settings.delete_org_title = Eliminar l'organització settings.delete_org_desc = Aquesta organització s'eliminarà permanentment. Voleu continuar? settings.labels_desc = Afegiu etiquetes que poden ser usades a totes les incidències de tots els repositoris d'aquesta organització. -members.private = Ocult +members.private = Amagat members.member_role = Funció del membre: members.owner = Propietari members.member = Membre @@ -1665,6 +2739,58 @@ teams.invite_team_member = Convidar a %s teams.invite_team_member.list = Invitacions pendents teams.delete_team_title = Eliminar l'equip +members = Membres +teams = Equips +code = Codi +lower_members = membres +lower_repositories = repositoris +org_desc = Descripció +team_name = Nom de l'equip +team_desc = Descripció + +org_name_holder = Nom de l'organització +org_full_name_holder = Nom complet de l'organització +org_name_helper = Els noms d'organització han de ser curts i memorables. +create_org = Crear organització +open_dashboard = Obrir tauler +repo_updated = Actualitzat %s +create_new_team = Nou equip +create_team = Crear equip +team_name_helper = Els noms d'equip han de ser curts i memorables. +team_desc_helper = Descriviu l'objectiu o rol de l'equip. +team_permission_desc = Permís +team_unit_desc = Permetre accés a seccions del repositori +team_unit_disabled = (Desactivat) +follow_blocked_user = No podeu seguir aquesta organització perquè us ha bloquejat. +form.name_reserved = El nom d'organització "%s" és reservat. +form.name_pattern_not_allowed = El patró "%s" no està permès en un nom d'organització. +form.create_org_not_allowed = No teniu permisos per crear una organització. +settings.repoadminchangeteam = L'administrador del repositori pot donar-ne i treure'n l'accés als equips +settings.change_orgname_prompt = Nota: Canviar el nom de l'organització també en canviarà l'URL i alliberarà el nom antic. +settings.change_orgname_redirect_prompt.with_cooldown.one = El nom antic de l'organització serà disponible a tothom després d'un període de protecció de %[1]d dia. Encara podreu reclamar el nom antic durant el període de protecció. +settings.change_orgname_redirect_prompt.with_cooldown.few = El nom antic de l'organització serà disponible a tothom després d'un període de protecció de %[1]d dies. Encara podreu reclamar el nom antic durant el període de protecció. +settings.hooks_desc = Afegir webhooks que s'activaran a tots els repositoris en aquesta organització. +members.public_helper = Ocultar +members.private_helper = Fer visible +members.leave = Marxar +teams.admin_access_helper = Els membres poden pujar (push) i baixar (pull) als repositoris de l'equip i afegir-hi col·laboradors. +teams.delete_team_desc = Eliminar un equip fa que els seus membres perdin accés al repositori. Continuar? +teams.delete_team_success = S'ha eliminat l'equip. +teams.admin_permission_desc = Aquest equip atorga accés d'administrador: els membres poden veure els repositoris de l'equip, pujar-hi (push) i afegir-hi col·laboradors. +teams.remove_all_repos_desc = Això eliminarà tots els repositoris de l'equip. +teams.add_all_repos_desc = Això afegirà tots els repositoris de l'organització a l'equip. +teams.add_nonexistent_repo = El repositori que voleu afegir no existeix. Si us plau, creeu-lo. +teams.add_duplicate_users = L'usuari ja és un membre de l'equip. +teams.repos.none = Aquest equip no pot accedir a cap repositori. +teams.members.none = No hi ha membres a l'equip. +teams.specific_repositories = Repositoris específics +teams.specific_repositories_helper = Els membres només tindran accés a repositoris afegits explícitament a l'equip. Seleccionar això no eliminarà automàticament els repositoris ja afegits a Tots els repositoris. +teams.all_repositories = Tots els repositoris +teams.all_repositories_helper = L'equip té accés a tots els repositoris. Seleccionar això afegirà tots els repositoris a l'equip. +teams.invite.title = Heu sigut convidats a unir-vos a l'equip %s a l'organització %s. +teams.invite.by = convidat per %s +teams.invite.description = Si us plau, feu clic al botó aquí sota per unir-vos a l'equip. + [admin] dashboard.cron.finished = Cron: %[1]s ha finalitzat dashboard.delete_inactive_accounts = Suprimir tots els comptes no activats @@ -1675,4 +2801,489 @@ dashboard.delete_missing_repos = Suprimir tots els repositoris que no tinguin el dashboard.delete_missing_repos.started = S'ha iniciat la tasca per suprimir tots els repositoris que no tinguin els fitxers de Git. dashboard.update_mirrors = Actualitzar les rèpliques dashboard.archive_cleanup = Suprimir els arxius de repositori antics -dashboard.memory_allocate_times = Assignacions de memòria \ No newline at end of file +dashboard.memory_allocate_times = Assignacions de memòria +repositories = Repositoris +hooks = Webhooks +users.name = Nom d'usuari +users.full_name = Nom complet +users.activated = Activat +users.admin = Administrador +users.list_status_filter.is_admin = Administrador +emails.activated = Activat +emails.filter_sort.email = Correu electrònic +emails.filter_sort.name = Nom d'usuari +orgs.name = Nom +orgs.teams = Equips +orgs.members = Membres +orgs.new_orga = Nova organització +repos.name = Nom +repos.issues = Problemes +repos.size = Mida +packages.name = Nom +packages.version = Versió +packages.type = Tipus +packages.repository = Repositori +packages.size = Mida +auths.name = Nom +auths.type = Tipus +auths.enabled = Habilitat +auths.host = Amfitrió +auths.port = Port +config.ssh_enabled = Habilitat +config.ssh_port = Port +config.lfs_enabled = Habilitat +config.db_type = Tipus +config.db_host = Amfitrió +config.db_name = Nom +config.db_user = Nom d'usuari +config.db_schema = Esquema +config.db_ssl_mode = SSL +config.db_path = Camí +config.mailer_enabled = Habilitat +config.mailer_name = Nom +monitor.name = Nom +monitor.queue.name = Nom +monitor.queue.type = Tipus +notices.type = Tipus +notices.type_1 = Repositori +notices.desc = Descripció + +dashboard = Tauler +self_check = Comprovació automàtica +identity_access = Identitat i accés +users = Comptes d'usuari +organizations = Organitzacions +assets = Recursos de codi +integrations = Integracions +authentication = Fonts d'autentificació +emails = Adreces de correu electrònic d'usuaris +config = Configuració +config_summary = Resum +config_settings = Configuració +monitor = Monitoratge +first_page = Primer +last_page = Últim +total = Total: %d +settings = Configuració d'administrador +dashboard.new_version_hint = Forgejo %s és ara disponible, esteu executant %s. Comprova el blog per més detalls. +dashboard.statistic = Resum +dashboard.operations = Operacions de manteniment +dashboard.system_status = Estat del sistema +dashboard.operation_name = Nom d'operació +dashboard.clean_unbind_oauth = Neteja les connexions OAuth desenllaçades +dashboard.delete_generated_repository_avatars = Suprimir els avatars de repositori generats +dashboard.sync_repo_tags = Sincronitzar les etiquetes de les dades de Git a la base de dades +dashboard.repo_health_check = Comprovar la salut de tots els repositoris + +notices = Notificacions del sistema +dashboard.operation_switch = Intercanvia +dashboard.operation_run = Executar +dashboard.clean_unbind_oauth_success = S'han eliminat totes les connexions OAuth desenllaçades. +dashboard.task.started = Tasca iniciada: %[1]s +dashboard.task.process = Tasca: %[1]s +dashboard.task.cancelled = Tasca: %[1]s cancel·lada: %[3]s +dashboard.task.error = Error en la tasca: %[1]s: %[3]s +dashboard.task.finished = Tasca: %[1] iniciada per %[2s] ha finalitzat +dashboard.task.unknown = Tasca desconeguda: %[1]s +dashboard.cron.started = Cron iniciat: %[1]s +dashboard.cron.process = Cron: %[1]s +dashboard.cron.cancelled = Cron: %[1]s cancel·lat: %[3]s +dashboard.cron.error = Error amb Cron: %s: %[3]s +dashboard.sync_repo_branches = La sincronització ha ignorat branques de les dades Git a la base de dades +dashboard.check_repo_stats = Comprovar totes les estadístiques del repositori +dashboard.deleted_branches_cleanup = Netejar branques eliminades +dashboard.update_migration_poster_id = Actualitza les ID de l'autor de migració +dashboard.git_gc_repos = Recull la brossa de tots els repositoris +dashboard.resync_all_sshkeys = Actualitzar el fitxer ".ssh/authorized_keys" amb les claus SSH de Forgejo. +dashboard.resync_all_sshprincipals = Actualitzar el fitxer ".ssh/authorized_principals" amb els principals SSH de Forgejo. +dashboard.resync_all_hooks = Resincronitzar els ganxos Git de tots els repositoris (pre-receive, update, post-receive, proc-receive, …) +dashboard.reinit_missing_repos = Reinicialitza tots els repositoris Git que falten i que tenen registres +dashboard.sync_external_users = Sincronitzar dades d'usuari externes +dashboard.cleanup_hook_task_table = Netejar la taula hook_task +dashboard.cleanup_packages = Netejar paquets caducats +dashboard.cleanup_actions = Netejar registres i artefactes d'accions caducats +dashboard.server_uptime = Temps de funcionament del servidor +dashboard.current_goroutine = Goroutines actuals +dashboard.current_memory_usage = Ús de memòria actual +dashboard.total_memory_allocated = Total de memòria adjudicada +dashboard.memory_obtained = Memòria rebuda +dashboard.pointer_lookup_times = Temps de consulta dels punters +dashboard.memory_free_times = Alliberaments de memòria +dashboard.current_heap_usage = Ús del heap actual +dashboard.heap_memory_obtained = Memòria de heap rebuda +dashboard.heap_memory_idle = Memòria del heap en repòs +dashboard.heap_memory_in_use = Memòria del heap en ús +dashboard.heap_memory_released = Memòria del heap alliberada +dashboard.heap_objects = Objectes del heap +dashboard.bootstrap_stack_usage = Ús de l'arrancada de la pila (stack) +dashboard.stack_memory_obtained = Memòria de la pila (stack) rebuda +dashboard.mspan_structures_usage = Ús de les estructures MSpan +dashboard.mspan_structures_obtained = Estructures MSpan rebudes +dashboard.mcache_structures_usage = Ús de les estructures MCache +dashboard.mcache_structures_obtained = Estructures MCache rebudes +dashboard.gc_metadata_obtained = Metadades del GC rebudes +dashboard.next_gc_recycle = Proper cicle de GC +dashboard.last_gc_time = Temps des del darrer GC +dashboard.total_gc_pause = Pausa total de GC +dashboard.last_gc_pause = Darrera pausa de GC +dashboard.delete_old_actions = Eliminar totes les activitats antigues de la base de dades +dashboard.delete_old_actions.started = Eliminar totes les activitats antigues des que s'ha iniciat la base de dades. +dashboard.delete_old_system_notices = Eliminar totes les notificacions de sistema antigues de la base de dades +dashboard.gc_lfs = Recull la brossa d'objectes meta LFS +dashboard.stop_zombie_tasks = Aturar tasques d'accions zombi +dashboard.stop_endless_tasks = Aturar tasques d'accions infinites +dashboard.cancel_abandoned_jobs = Cancel·lar feines d'accions abandonades +dashboard.sync_branch.started = S'ha iniciat la sincronització de branca +dashboard.sync_tag.started = S'ha iniciat la sincronització d'etiquetes +dashboard.rebuild_issue_indexer = Reconstruir l'indexador d'incidències +users.user_manage_panel = Gestionar comptes d'usuari +users.new_account = Crear compte d'usuari +users.restricted = Restringit +users.reserved = Reservat +users.bot = Bot +users.remote = Remot +users.2fa = A2F +users.repos = Repos +users.created = Creats +users.last_login = Darrer inici de sessió +users.never_login = Mai ha iniciat sessió +users.send_register_notify = Notificar sobre el registre per correu +users.new_success = S'ha creat l'usuari "%s". +users.edit = Editar +users.auth_source = Font d'autenticació +users.local = Local +users.auth_login_name = Nom d'autenticació de sessió +users.password_helper = Deixeu la contrasenya buida si no la voleu canviar. +users.update_profile_success = S'ha actualitzat el compte d'usuari. +users.edit_account = Editar compte d'usuari +users.max_repo_creation = Nombre màxim de repositoris +users.max_repo_creation_desc = (Introduïu -1 per usar el límit global predeterminat.) +users.is_activated = Compte actiu +users.activated.description = Completar la verificació per correu. L'usuari d'un compte inactiu no podrà iniciar-hi sessió fins que n'hagi verificat el correu. +users.prohibit_login = Compte suspès +users.block.description = Fa que l'usuari no pugui interactuar amb aquest servei a través del seu compte i en prohibeix l'inici de sessió. +users.is_admin = Compte d'administrador +users.admin.description = Dona accés complet a totes les funcions d'administració a través de la interfície web i l'API. +users.is_restricted = Compte restringit +users.restricted.description = Només permet interactuar amb repositoris i organitzacions quan l'usuari n'és col·laborador. Això no permet l'accés als repositoris públics d'aquesta instància. +users.allow_git_hook = Pot crear ganxos Git +users.allow_git_hook_tooltip = Els ganxos Git s'executen com a l'usuari del sistema operatiu on corre Forgejo, i tenen el mateix nivell d'accés a l'amfitrió. Per tant, els usuaris amb aquest privilegi especial poden accedir i modificar tots els repositoris de Forgejo, així com la base de dades que fa servir Forgejo. Això també els permet obtenir privilegis d'administrador a Forgejo. +users.allow_import_local = Pot importar repositoris locals +users.local_import.description = Permet la importació de repositoris des del sistema de fitxers local del servidor. Això pot ser un problema de seguretat. +users.allow_create_organization = Pot crear organitzacions +users.organization_creation.description = Permet crear noves organitzacions. +users.update_profile = Actualitzar compte d'usuari +users.delete_account = Eliminar compte d'usuari +users.cannot_delete_self = No podeu eliminar-vos vós mateix +users.still_own_repo = Aquest usuari encara té un o més repositoris. Elimineu-los o transferiu-los abans. +users.still_has_org = Aquest usuari és membre d'una organització. Elimineu-lo de totes les organitzacions abans. +users.purge = Purgar usuari +users.purge_help = Elimina forçosament l'usuari i tots els seus repositoris, organitzacions i paquets. També s'eliminaran tots els seus comentaris i incidències. +users.still_own_packages = Aquest usuari encara té un o més paquets. Elimineu-los abans. +users.deletion_success = S'ha eliminat l'usuari. +users.reset_2fa = Restableix l'A2F +users.list_status_filter.menu_text = Filtrar +users.list_status_filter.reset = Restaurar +users.list_status_filter.is_active = Actiu +users.list_status_filter.not_active = Inactiu +users.list_status_filter.not_admin = No administrador +users.list_status_filter.is_restricted = Restringit +users.list_status_filter.not_restricted = No restringit +users.list_status_filter.is_prohibit_login = Inici de sessió prohibit +users.list_status_filter.not_prohibit_login = Inici de sessió permès +users.list_status_filter.is_2fa_enabled = A2F activada +users.list_status_filter.not_2fa_enabled = A2F desactivada +users.details = Detalls d'usuari +emails.email_manage_panel = Gestionar correus d'usuari +emails.primary = Principal +emails.filter_sort.email_reverse = Correu (invers) +emails.filter_sort.name_reverse = Nom d'usuari (invers) +emails.updated = Correu actualitzat +emails.not_updated = No s'ha pogut actualitzar l'adreça de correu: %v +emails.duplicate_active = Aquesta adreça de correu ja pertany a un altre usuari. +emails.change_email_header = Actualitzar propietats del correu +emails.change_email_text = Esteu segur que voleu modificar aquesta adreça de correu? +emails.delete = Eliminar adreça de correu +emails.delete_desc = Esteu segur que voleu eliminar aquesta adreça de correu? +emails.deletion_success = S'ha eliminat l'adreça de correu. +emails.delete_primary_email_error = No podeu eliminar l'adreça de correu principal. +orgs.org_manage_panel = Gestionar organitzacions +repos.repo_manage_panel = Gestionar repositoris +repos.unadopted = Repositoris no-adoptats +repos.unadopted.no_more = No s'han trobat repositoris no-adoptats. +repos.owner = Propietari +repos.lfs_size = Mida LFS +packages.package_manage_panel = Gestionar paquets +packages.total_size = Mida total: %s +packages.unreferenced_size = Mida sense referenciar: %s +packages.cleanup = Netejar les dades caducades +packages.cleanup.success = S'han netejat les dades caducades satisfactòriament +packages.owner = Propietari +packages.creator = Creador +packages.published = Publicat +defaulthooks = Webhooks predeterminats +defaulthooks.desc = Els webhooks fan una petició automàtica HTTP POST a un servidor quan s'activen alguns esdeveniments de Forgejo. Els webhooks definits aquí són predeterminats i es copiaran a tots els nous repositoris. Llegiu-ne més en la guia de webhooks. +defaulthooks.add_webhook = Afegir webhook per defecte +defaulthooks.update_webhook = Actualitzar webhook per defecte +systemhooks = Webhooks del sistema +systemhooks.desc = Els webhooks fan una petició automàtica HTTP POST a un servidor quan s'activen alguns esdeveniments de Forgejo. Els webhooks definits aquí s'aplicaran a tots els repositoris del sistema, així que considereu l'impacte que poden tenir en el rendiment. Llegiu-ne més en la guia de webhooks. +systemhooks.add_webhook = Afegir webhook de sistema +systemhooks.update_webhook = Actualitzar webhook de sistema +auths.auth_manage_panel = Gestionar fonts d'autenticació +auths.new = Afegir font d'autenticació +auths.syncenabled = Activar la sincronització d'usuaris +auths.updated = Actualitzat +auths.auth_type = Tipus d'autenticació +auths.auth_name = Nom d'autenticació +auths.security_protocol = Protocol de seguretat +auths.bind_dn = DN bind +auths.bind_password = Contrasenya bind +auths.user_base = Base de cerca d'usuari +auths.user_dn = DN d'usuari +auths.attribute_username = Atribut de nom d'usuari +auths.attribute_username_placeholder = Deixeu-ho buit per usar el nom d'usuari de Forgejo. +auths.attribute_name = Atribut de nom +auths.attribute_surname = Atribut de cognom +auths.attribute_mail = Atribut de correu electrònic +auths.attribute_ssh_public_key = Atribut de clau pública SSH +auths.attribute_avatar = Atribut d'avatar +auths.attributes_in_bind = Recupera els atributs del context bind DN +auths.default_domain_name = Nom de domini per defecte usat per l'adreça de correu +auths.allow_deactivate_all = Permet que un resultat de cerca buit desactivi tots els usuaris +auths.use_paged_search = Usar cerca en pàgines +auths.search_page_size = Mida de pàgina +auths.filter = Filtre d'usuari +auths.admin_filter = Filtre d'administrador +auths.restricted_filter = Filtre restringit +auths.restricted_filter_helper = Deixeu-ho buit per no marcar cap usuari com a restringit. Useu un asterisc ("*") per marcar tots els usuaris que no coincideixin amb el Filtre d'administrador com a restringits. +auths.verify_group_membership = Verificar l'adhesió de grup a LDAP (deixeu el filtre buit per ignorar-ho) +auths.group_search_base = DN base de cerca de grup +auths.group_attribute_list_users = Atribut de grup amb la llista d'usuaris +auths.user_attribute_in_group = Atribut d'usuari llistat en el grup +auths.map_group_to_team = Assigna els grups LDAP a equips d'organització (deixeu-ho buit per saltar-ho) +auths.map_group_to_team_removal = Elimina els usuaris dels equips sincronitzats si no pertanyen al grup LDAP corresponent +auths.enable_ldap_groups = Activar grups LDAP +auths.smtp_auth = Tipus d'autenticació SMTP +auths.smtphost = Amfitrió SMTP +auths.smtpport = Port SMTP +auths.allowed_domains = Dominis permesos +auths.allowed_domains_helper = Deixeu-ho buit per permetre tots els dominis. Separeu múltiples dominis amb una coma (","). +auths.skip_tls_verify = Salta't la verificació TLS +auths.force_smtps = Força l'SMTPS +auths.force_smtps_helper = L'SMTPS sempre usa el port 465. Indiqueu això per forçar l'SMTPS en un altre port. (Sinó s'usarà l'STARTTLS en altres ports, sempre que l'amfitrió ho suporti.) +auths.helo_hostname = Hostname HELO +auths.helo_hostname_helper = Hostname enviat amb HELO. Deixeu-ho en blanc per enviar el hostname actual. +auths.disable_helo = Deshabilita HELO +auths.pam_service_name = Nom de servei PAM +auths.pam_email_domain = Domini de correu PAM (opcional) +auths.oauth2_provider = Proveïdor OAuth2 +auths.oauth2_icon_url = URL d'icona +auths.oauth2_clientID = ID de client (clau) +auths.oauth2_clientSecret = Secret de client +auths.openIdConnectAutoDiscoveryURL = URL d'OpenID Connect Auto Discovery +auths.oauth2_use_custom_url = Usar URL personalitzades enlloc d'URL predeterminades +auths.oauth2_tokenURL = URL de testimoni (token) +auths.oauth2_authURL = URL d'autorització +auths.oauth2_profileURL = URL de perfil +auths.oauth2_emailURL = URL de correu +auths.skip_local_two_fa = Salta l'A2F local +auths.skip_local_two_fa_helper = No marcar aquesta opció farà que els usuaris que tenen l'A2F definida igualment hauran de passar l'A2F per iniciar sessió +auths.oauth2_tenant = Tenant +auths.oauth2_scopes = Àmbits addicionals +auths.oauth2_required_claim_value_helper = Assigneu aquest valor per restringir l'inici de sessió des d'aquesta font als usuaris que declarin aquest nom i valor +auths.oauth2_map_group_to_team_removal = Elimina els usuaris dels equips sincronitzats si no pertanyen al grup corresponent. +auths.tips = Consells +auths.tips.gmail_settings = Configuracions de Gmail: +auths.tips.oauth2.general = Autenticació OAuth2 +auths.tips.oauth2.general.tip = Quan registreu una nova autenticació OAuth2, l'URL de crida/redirecció serà: +auths.tip.oauth2_provider = Proveïdor OAuth2 +auths.tip.bitbucket = Registreu un nou consumidor OAuth2 a %s i afegiu els permisos "Compte" - "Lectura" +auths.tip.nextcloud = Registreu un nou consumidor OAuth en la vostra instància amb el menú "Configuració -> Seguretat -> Client OAuth 2.0" +auths.tip.dropbox = Crea una nova aplicació a %s +auths.tip.facebook = Registreu una nova aplicació a %s i afegiu el producte "Facebook Login" +auths.tip.github = Registra una aplicació OAuth nova a %s +auths.tip.gitlab_new = Registra una aplicació nova a %s +auths.tip.google_plus = Obté les credencials del client OAuth2 amb la consola del Google API a %s +auths.tip.openid_connect = Usa l'URL d'OpenID Connect Discovery (/.well-known/openid-configuration) per a especificar els endpoints +auths.tip.mastodon = Introduïu l'URL a una instància diferent de Mastodon amb la que voleu autenticar-vos (o bé useu la instància per defecte) +auths.edit = Editar font d'autenticació +auths.activated = S'ha activat aquesta font d'autenticació +auths.new_success = S'ha afegit l'autenticació "%s". +auths.update_success = S'ha actualitzat la font d'autenticació. +auths.update = Actualitzar font d'autenticació +auths.delete = Eliminar font d'autenticació +auths.delete_auth_title = Eliminar font d'autenticació +auths.delete_auth_desc = Eliminar una font d'autenticació fa que els usuaris que en fan ús no puguin iniciar sessió. Continuar? +auths.still_in_used = Aquesta font d'autenticació encara s'utilitza. Convertiu o elimineu els usuaris que en fan ús abans. +auths.deletion_success = S'ha eliminat la font d'autenticació. +auths.login_source_exist = La font d'autenticació "%s" ja existeix. +auths.unable_to_initialize_openid = No s'ha pogut inicialitzar el proveïdor d'OpenID Connect: %s +auths.invalid_openIdConnectAutoDiscoveryURL = URL d'Auto Discovery invàlida (ha de ser una URL vàlida començant amb http:// o https://) +config.server_config = Configuració de servidor +config.app_name = Títol de la instància +config.app_slogan = Eslògan de la instància +config.app_ver = Versió de Forgejo +config.app_url = URL base +config.custom_conf = Camí al fitxer de configuració +config.custom_file_root_path = Camí arrel dels fitxers personalitzada +config.domain = Domini del servidor +config.offline_mode = Mode local +config.disable_router_log = Desactiva els registres de l'encaminador +config.run_user = Executa com a usuari +config.run_mode = Mode d'execució +config.git_version = Versió de Git +config.app_data_path = Camí a les dades d'aplicació +config.repo_root_path = Camí arrel del repositori +config.log_file_root_path = Camí de registres +config.script_type = Tipus d'script +config.reverse_auth_user = Usuari d'autenticació al servidor intermediari revers +config.ssh_config = Configuració SSH +config.ssh_start_builtin_server = Usa el servidor integrat +config.ssh_domain = Domini del servidor SSH +config.ssh_listen_port = Port d'escolta +config.ssh_root_path = Camí arrel +config.ssh_key_test_path = Camí al test de clau +config.ssh_keygen_path = Camí keygen ("ssh-keygen") +config.ssh_minimum_key_size_check = Comprovació mínima de la mida de clau +config.ssh_minimum_key_sizes = Mides mínimes de clau +config.lfs_config = Configuració LFS +config.lfs_content_path = Camí de contingut LFS +config.lfs_http_auth_expiry = Temps de caducitat d'autenticació HTTP de l'LFS +config.db_config = Configuració de la base de dades +config.service_config = Configuració del servei +config.register_email_confirm = Requereix una confirmació de correu per a registrar-se +config.disable_register = Deshabilita l'auto-registre +config.allow_only_internal_registration = Permet el registre només a través de Forgejo +config.allow_only_external_registration = Permet el registre només a través de serveis externs +config.enable_openid_signup = Habilita l'auto-registre amb OpenID +config.enable_openid_signin = Habilita l'inici de sessió amb OpenID +config.show_registration_button = Mostra el botó de registre +config.require_sign_in_view = Requereix iniciar sessió per veure el contingut +config.mail_notify = Habilita les notificacions per correu +config.enable_captcha = Habilita el CAPTCHA +config.active_code_lives = Temps de caducitat del codi d'activació +config.reset_password_code_lives = Temps de caducitat del codi de recuperació +config.default_keep_email_private = Amaga les adreces de correu, per defecte +config.default_allow_create_organization = Permet crear organitzacions, per defecte +config.enable_timetracking = Habilita el seguiment de temps +config.default_enable_timetracking = Habilita el seguiment de temps, per defecte +config.allow_dots_in_usernames = Permet que el usuaris utilitzin punts en el nom d'usuari. Això no afecta als comptes que ja existeixen. +config.default_allow_only_contributors_to_track_time = Fes que només els contribuïdors puguin fer un seguiment de temps +config.no_reply_address = Domini del correu ocult +config.default_visibility_organization = Visibilitat per defecte de les noves organitzacions +config.default_enable_dependencies = Habilita les dependències d'incidències, per defecte +config.webhook_config = Configuració dels Webhooks +config.queue_length = Longitud de la cua +config.deliver_timeout = Temps d'espera d'entrega +config.skip_tls_verify = Salta't la verificació TLS +config.mailer_config = Configuració del remitent +config.mailer_enable_helo = Habilita HELO +config.mailer_protocol = Protocol +config.mailer_smtp_addr = Amfitrió SMTP +config.mailer_smtp_port = Port SMTP +config.mailer_user = Usuari +config.mailer_use_sendmail = Usa Sendmail +config.mailer_sendmail_path = Camí de Sendmail +config.mailer_sendmail_args = Arguments extra per Sendmail +config.mailer_sendmail_timeout = Temps d'espera per Sendmail +config.test_email_placeholder = Correu electrònic (ex. test@example.com) +config.send_test_mail = Envia un correu de prova +config.send_test_mail_submit = Envia +config.test_mail_failed = No s'ha pogut enviar el correu de prova a "%s": %v +config.test_mail_sent = S'ha enviat un correu de prova a "%s". +config.cache_config = +config.cache_adapter = Adaptador de la memòria cau +config.cache_interval = Interval de la memòria cau +config.cache_conn = Connexió de la memòria cau +config.cache_item_ttl = TTL dels ítems de la memòria cau +config.cache_test = Prova la memòria cau +config.cache_test_failed = No s'ha pogut examinar la memòria cau: %v. +config.cache_test_slow = La memòria cau s'ha provat correctament, però la resposta és lenta: %s. +config.cache_test_succeeded = La memòria cau s'ha provat correctament, s'ha rebut una resposta en %s. +config.session_config = Configuració de la sessió +config.session_provider = Proveïdor de la sessió +config.provider_config = Configuració del proveïdor +config.cookie_name = Nom de la galeta +config.gc_interval_time = Interval de temps del GC +config.session_life_time = Temps de vida de la sessió +config.https_only = Només HTTPS +config.picture_config = Configuració d'imatge i avatar +config.disable_gravatar = Deshabilita Gravatar +config.enable_federated_avatar = Habilita els avatars federats + +dashboard.update_checker = Comprovador d'actualització + +[actions] +runners.name = Nom +runners.owner_type = Tipus +runners.description = Descripció +runners.labels = Etiquetes +runners.task_list.repository = Repositori +runners.task_list.commit = Commit +runners.version = Versió +runs.commit = Commit +runs.no_workflows.help_write_access = No sabeu com començar amb Forgejo Actions? Feu un cop d'ull als primers passos a la documentació d'usuari per escriure el vostre primer flux de treball, llavors configureu un runner Forgejo per a executar els vostres treballs. +runs.no_workflows.help_no_write_access = Per saber-ne més sobre Forgejo Actions, vegeu la documentació. +variables = Variables +variables.management = Gestionar variables +variables.creation = Afegir variables +variables.none = Encara no hi ha variables. +variables.deletion = Eliminar variable +variables.deletion.description = Eliminar una variable és permanent i no es pot desfer. Continua? +variables.description = Les variables es passaran a certes accions i no es poden llegir altrament. +variables.edit = Editar variable +variables.not_found = No s'ha trobat la variable. +variables.deletion.failed = No s'ha pogut eliminar la variable. +variables.deletion.success = S'ha canviar el nom de la variable. +variables.creation.failed = No s'ha pogut afegir la variable. +variables.creation.success = S'ha afegit la variable "%s". +variables.update.failed = No s'ha pogut editar la variable. +variables.update.success = S'ha editat la variable. + +[repo.permissions] +code.read = Lectura: Accedir i clonar el codi del repositori. +code.write = Escriptura: Pujar (push) al repositori, crear branques i etiquetes. +issues.read = Lectura: Llegir i crear incidències i comentaris. +issues.write = Escriptura: Tancar incidències i gestionar metadades com etiquetes, fites, assignacions, terminis i dependències. +pulls.read = Lectura: Llegir i crear «pull requests». +pulls.write = Escriptura: Tancar «pull requests» i gestionar metadades com etiquetes, fites, assignacions, terminis i dependències. +releases.read = Lectura: Veure i baixar publicacions. +releases.write = Escriptura: Publicar, editar i eliminar publicacions i els seus recursos. +wiki.read = Lectura: Llegir la wiki integrada i el seu historial. +wiki.write = Escriptura: Crear, modificar i eliminar pàgines en la wiki integrada. +projects.read = Lectura: Accedir els taulells de projecte del repositori. +projects.write = Escriptura: Crear projectes i columnes, i editar-los. +packages.read = Lectura: Llegir i baixar paquets assignats al repositori. +packages.write = Escriptura: Publicar i eliminar paquets assignats al repositori. +actions.read = Lectura: Veure l'execució dels fluxos de treball i els seus registres (logs). +actions.write = Escriptura: Activar, reiniciar i cancel·lar fluxos de treball. Gestionar la delegació de confiança als autors de «pull requests». +ext_issues = Accedir a l'enllaç a un gestor d'incidències extern. Els permisos es gestionen allà. +ext_wiki = Accedir a l'enllaç a una wiki externa. Els permisos es gestionen allà. + +[graphs] +component_loading = Carregant %s… +component_loading_failed = No s'ha pogut carregar %s +component_loading_info = Això trigarà una estona… +component_failed_to_load = Ha passat un error inesperat. +code_frequency.what = freqüència de codi +contributors.what = contribucions +recent_commits.what = commits recents + +[secrets] +secrets = Secrets +description = Els secrets es passaran a certes accions i no es poden llegir altrament. +none = Encara no hi ha secrets. +creation = Afegir secret +creation.success = S'ha afegit el secret "%s". +creation.failed = No s'ha pogut afegir el secret. +deletion = Eliminar secret +deletion.description = Eliminar un secret és permanent i no es pot desfer. Continua? +deletion.success = S'ha eliminat el secret. +deletion.failed = No s'ha pogut eliminar el secret. +management = Gestionar secrets + +[projects] +deleted.display_name = Projecte eliminat +type-1.display_name = Projecte individual +type-2.display_name = Projecte del repositori +type-3.display_name = Projecte de l'organització \ No newline at end of file diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index d3626ed677..9a59271ac1 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -609,7 +609,7 @@ organization_leave_success=Úspěšně jste opustili organizaci %s. invalid_ssh_key=Nepodařilo se ověřit váš klíč SSH: %s invalid_gpg_key=Nepodařilo se ověřit váš klíč GPG: %s -invalid_ssh_principal=Neplatný SSH Principal certifikát: %s +invalid_ssh_principal=Neplatný principal: %s must_use_public_key=Zadaný klíč je soukromý klíč. Nenahrávejte svůj soukromý klíč nikde. Místo toho použijte váš veřejný klíč. unable_verify_ssh_key=Nepodařilo se ověřit klíč SSH, zkontrolujte, zda neobsahuje chyby. auth_failed=Ověření selhalo: %v @@ -805,7 +805,7 @@ key_content_gpg_placeholder=Začíná s „-----BEGIN PGP PUBLIC KEY BLOCK----- add_new_principal=Přidat principal ssh_key_been_used=Tento klíč SSH byl na server již přidán. ssh_key_name_used=U vašeho účtu již existuje klíč SSH se stejným názvem. -ssh_principal_been_used=Tento SSH Principal certifikát již byl přidán na server. +ssh_principal_been_used=Tento principal již byl přidán na server. gpg_key_id_used=Veřejný klíč GPG se stejným ID již existuje. gpg_no_key_email_found=Tento klíč GPG neodpovídá žádné aktivované e-mailové adrese spojené s vaším účtem. Může být stále přidán, pokud podepíšete zadaný token. gpg_key_matched_identities=Odpovídající identity: @@ -847,7 +847,7 @@ gpg_key_deletion_desc=Odstraněním klíče GPG zneplatníte ověření revizí, ssh_principal_deletion_desc=Odstranění SSH Principal certifikátu zruší jeho přístup k vašemu účtu. Pokračovat? ssh_key_deletion_success=Klíč SSH byl odstraněn. gpg_key_deletion_success=Klíč GPG byl odstraněn. -ssh_principal_deletion_success=SSH Principal certifikát byl odstraněn. +ssh_principal_deletion_success=Principal byl odstraněn. added_on=Přidáno %s valid_until_date=Platné do %s valid_forever=Platné navždy @@ -857,7 +857,7 @@ can_read_info=Čtení can_write_info=Zápis key_state_desc=Tento klíč byl použit během posledních 7 dní token_state_desc=Tento token byl použit během posledních 7 dní -principal_state_desc=Tento SSH Principal certifikát byl použit během posledních 7 dní +principal_state_desc=Tento principal certifikát byl použit během posledních 7 dní show_openid=Zobrazit na profilu hide_openid=Odstranit z profilu ssh_disabled=SSH je zakázáno diff --git a/options/locale/locale_da.ini b/options/locale/locale_da.ini index f9db1298e0..f2d4852f55 100644 --- a/options/locale/locale_da.ini +++ b/options/locale/locale_da.ini @@ -187,8 +187,8 @@ more = Mere [editor] buttons.heading.tooltip = Tilføj overskrift -buttons.bold.tooltip = Tilføj fed tekst -buttons.italic.tooltip = Tilføj kursiv tekst +buttons.bold.tooltip = Tilføj fed tekst (Ctrl+B / ⌘B) +buttons.italic.tooltip = Tilføj kursiv tekst (Ctrl+I / ⌘I) buttons.quote.tooltip = Citat tekst buttons.code.tooltip = Tilføj kode buttons.link.tooltip = Tilføj et link @@ -348,7 +348,7 @@ require_sign_in_view.description = Begræns indholdsadgang til ind-loggede bruge default_allow_create_organization.description = Tillad nye brugere at oprette organisationer som standard. Når denne mulighed er deaktiveret, skal en administrator give tilladelse til at oprette organisationer til nye brugere. password_algorithm = Adgangskode hash algoritme enable_update_checker_helper_forgejo = Den vil med jævne mellemrum tjekke for nye Forgejo versioner ved at tjekke en TXT DNS-posten på release.forgejo.org. -password_algorithm_helper = Indstil adgangskode-hash-algoritmen. Algoritmer har forskellige krav og styrke. Argon2-algoritmen er ret sikker, men bruger meget hukommelse og kan være upassende til små systemer. +password_algorithm_helper = Indstil adgangskode-hash-algoritmen. Algoritmer har forskellige krav og styrker. Argon2-algoritmen er ret sikker, men bruger meget hukommelse og kan være upassende til små systemer. openid_signup.description = Tillad brugere at oprette konti via OpenID, hvis selvregistrering er aktiveret. [home] @@ -865,7 +865,7 @@ key_content_ssh_placeholder = Begynder med "ssh-ed25519", "ssh-rsa", "ecdsa-sha2 gpg_key_matched_identities_long = De indlejrede identiteter i denne nøgle matcher de følgende aktiverede e-mailadresser for denne bruger. Commits, der matcher disse e-mailadresser, kan bekræftes med denne nøgle. gpg_key_deletion_success = GPG-nøglen er blevet fjernet. email_preference_set_success = E-mail-præference er blevet indstillet. -keep_email_private_popup = Din e-mailadresse vil ikke blive vist på din profil og vil ikke være standard for commits foretaget via webgrænsefladen, som f.eks. filupload, redigeringer og merge commits. I stedet kan en speciel adresse %s bruges til at linke commits til din konto. Denne mulighed vil ikke påvirke eksisterende commits. +keep_email_private_popup = E-mailadressen vil ikke blive vist på profilsiden og vil ikke være standard for commits foretaget via webgrænsefladen, som f.eks. filupload, redigeringer og merge commits. I stedet kan en speciel adresse %s bruges til at linke commits til brugerens konto. Denne mulighed vil ikke påvirke eksisterende commits. gpg_desc = Disse offentlige GPG-nøgler er knyttet til din konto og bruges til at bekræfte dine commits. Opbevar dine private nøgler sikkert, da de giver dig mulighed for at underskrive commits med din identitet. gpg_token_help = Du kan generere en signatur ved at bruge: ssh_key_verified_long = Nøglen er blevet bekræftet med et token og kan bruges til at bekræfte commits, der matcher enhver aktiveret e-mail-adresse for denne bruger. @@ -973,7 +973,7 @@ quota.applies_to_user = Følgende kvoteregler gælder for din konto quota.rule.exceeded.helper = Den samlede størrelse af objekter for denne regel har overskredet kvoten. storage_overview = Opbevaringsoversigt quota = Kvote -quota.applies_to_org = Følgende kontingentregler gælder for denne organisation +quota.applies_to_org = Følgende kvoteregler gælder for denne organisation quota.rule.exceeded = Oversteget quota.rule.no_limit = Ubegrænset quota.sizes.all = Alle @@ -1054,7 +1054,7 @@ mirror_sync = synkroniseret mirror_sync_on_commit = Synkroniser når commits er pushed mirror_address = Klon fra URL mirror_address_desc = Angiv eventuelle nødvendige legitimationsoplysninger i sektionen Autorisation. -mirror_address_url_invalid = Den angivne URL er ugyldig. Du skal escape alle komponenter i URL'en korrekt. +mirror_address_url_invalid = Den angivne URL er ugyldig. Du skal sikre dig at alle komponenter i URL'en er escapet korrekt. mirror_lfs = Stort fillager (LFS) mirror_lfs_desc = Aktiver spejling af LFS-data. mirror_lfs_endpoint = LFS-endepunkt @@ -1641,8 +1641,8 @@ issues.add_time_hours = Timer issues.add_time_sum_to_small = Ingen tid blev indtastet. issues.time_spent_from_all_authors = `Samlet tid brugt: %s` issues.time_spent_total = Samlet tid brugt -issues.unlock.title = Lås op for samtale om dette problem. -issues.lock.title = Lås samtale om dette problem. +issues.unlock.title = Lås samtale op +issues.lock.title = Lås samtale. issues.comment_on_locked = Du kan ikke kommentere på et låst problem. issues.delete = Slet issues.delete.title = Slet dette problem? @@ -1802,7 +1802,7 @@ pulls.manually_merged = Manuelt flettet pulls.merged_info_text = Grenen %s kan nu slettes. pulls.is_closed = Pull-anmodningen er blevet lukket. pulls.nothing_to_compare = Disse grene er lige store. Der er ingen grund til at oprette en pull-anmodning. -pulls.nothing_to_compare_have_tag = Den valgte gren/tag er ens. +pulls.nothing_to_compare_have_tag = De valgte grene/tags er ens. pulls.nothing_to_compare_and_allow_empty_pr = Disse grene er lige store. Denne PR vil være tom. pulls.has_pull_request = `Der findes allerede en pull-anmodning mellem disse grene: %[2]s#%[3]d` pulls.create = Opret pull-anmodning @@ -2684,7 +2684,7 @@ branch.included_desc = Denne gren er en del af standardgrenen branch.included = Inkluderet branch.create_new_branch = Opret en gren fra gren: branch.confirm_create_branch = Opret gren -branch.rename_branch_to = Omdøb "%s" til: +branch.rename_branch_to = Omdøber gren "%s". migrate.repo_desc_helper = Lad være tom for at importere eksisterende beskrivelse archive.nocomment = Det er ikke muligt at kommentere, fordi depotet er arkiveret. comment.blocked_by_user = Det er ikke muligt at kommentere, fordi du er blokeret af depots ejer eller forfatteren. @@ -2969,7 +2969,7 @@ dashboard.clean_unbind_oauth_success = Alle ubundne OAuth-forbindelser er blevet dashboard.task.started = Startet opgave: %[1]s dashboard.task.cancelled = Opgave: %[1]s annulleret: %[3]s dashboard.task.error = Fejl i Opgave: %[1]s: %[3]s -dashboard.resync_all_hooks = Gensynkroniser pre-receive, update og post-receive hooks for alle depoter +dashboard.resync_all_hooks = Gensynkroniser Git hooks for alle depoter (pre-receive, update, post-receive, proc-receive,...) dashboard.reinit_missing_repos = Geninitialiser alle manglende Git-depoter, som der findes poster for dashboard.sync_external_users = Synkroniser eksterne brugerdata dashboard.cleanup_hook_task_table = Oprydning hook_task tabel @@ -3673,7 +3673,7 @@ days = %d dage now = nu [repo.permissions] -actions.read = Læs: Se integrerede CI/CD-pipelines og deres logfiler. +actions.read = Læs: Se worklows og deres logfiler. releases.write = Skriv: Udgiv, rediger og slet udgivelser og deres aktiver. wiki.read = Læs: Læs den integrerede wiki og dens historie. wiki.write = Skriv: Opret, opdater og slet sider i den integrerede wiki. diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 3007546f37..89380d3424 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -9,7 +9,7 @@ sign_in_with_provider=Anmelden mit %s sign_in_or=oder sign_out=Abmelden sign_up=Registrieren -link_account=Account verbinden +link_account=Konto verbinden register=Registrieren version=Version powered_by=Betrieben mit %s @@ -41,7 +41,7 @@ webauthn_sign_in=Drücke den Knopf auf deinem Sicherheitsschlüssel. Wenn dein S webauthn_press_button=Drücke den Knopf auf deinem Sicherheitsschlüssel … webauthn_use_twofa=Zwei-Faktor-Authentifizierung via Handy verwenden webauthn_error=Dein Sicherheitsschlüssel konnte nicht gelesen werden. -webauthn_unsupported_browser=Dein Browser unterstützt derzeit keinen WebAuthn. +webauthn_unsupported_browser=Dein Browser unterstützt derzeit kein WebAuthn. webauthn_error_unknown=Ein unbekannter Fehler ist aufgetreten. Bitte versuche es erneut. webauthn_error_insecure=WebAuthn unterstützt nur sichere Verbindungen. Zum Testen über HTTP kannst du „localhost“ oder „127.0.0.1“ als Host verwenden webauthn_error_unable_to_process=Der Server konnte deine Anfrage nicht bearbeiten. @@ -80,7 +80,7 @@ rerun_all=Alle Jobs neu starten save=Speichern add=Hinzufügen add_all=Alle hinzufügen -remove=Löschen +remove=Entfernen remove_all=Alle entfernen remove_label_str=Element „%s“ entfernen edit=Bearbeiten @@ -100,10 +100,10 @@ copy_type_unsupported=Dieser Dateityp kann nicht kopiert werden write=Verfassen preview=Vorschau -loading=Laden … +loading=Wird geladen … error=Fehler -error404=Die Seite, die du versuchst aufzurufen, existiert nicht, wurde entfernt oder du bist nicht berechtigt, diese anzusehen. +error404=Die Seite, die du versuchst aufzurufen, existiert nicht oder wurde entfernt, oder du bist nicht berechtigt, diese anzusehen. go_back=Zurück never=Niemals @@ -152,7 +152,7 @@ more_items = Mehr Einträge invalid_data = Ungültige Daten: %v copy_generic = In die Zwischenablage kopieren test = Test -error413 = Du hast deine Quota ausgereizt. +error413 = Du hast dein Kontingent ausgereizt. new_repo.title = Neues Repository new_migrate.title = Neue Migration new_org.title = Neue Organisation @@ -202,7 +202,7 @@ table_modal.label.columns = Spalten link_modal.header = Einen Link hinzufügen link_modal.url = URL link_modal.description = Beschreibung -link_modal.paste_reminder = Hinweis: Wenn du einen URL in der Zwischenablage hast, kannst du durch einfügen im Editor direkt einen Link erstellen. +link_modal.paste_reminder = Hinweis: Wenn du eine URL in der Zwischenablage hast, kannst du durch Einfügen im Editor direkt einen Link erstellen. [filter] string.asc=A–Z @@ -244,7 +244,7 @@ path=Pfad sqlite_helper=Dateipfad zur SQLite3-Datenbank.
Gib einen absoluten Pfad an, wenn Forgejo als Service gestartet wird. reinstall_error=Du versuchst, in eine bereits existierende Forgejo-Datenbank zu installieren reinstall_confirm_message=Eine Neuinstallation mit einer bestehenden Forgejo-Datenbank kann mehrere Probleme verursachen. In den meisten Fällen solltest du deine vorhandene „app.ini“ verwenden, um Forgejo auszuführen. Wenn du weißt, was du tust, bestätige die folgenden Angaben: -reinstall_confirm_check_1=Die von der SECRET_KEY in app.ini verschlüsselten Daten können verloren gehen: Benutzer können sich unter Umständen nicht mit 2FA/OTP einloggen und Spiegel könnten nicht mehr richtig funktionieren. Mit der Ankreuzung dieses Kästchens bestätigst du, dass die aktuelle app.ini-Datei den korrekten SECRET_KEY enthält. +reinstall_confirm_check_1=Die vom SECRET_KEY in app.ini verschlüsselten Daten können verloren gehen: Benutzer können sich unter Umständen nicht mit 2FA/OTP einloggen und Spiegel könnten nicht mehr richtig funktionieren. Mit der Ankreuzung dieses Kästchens bestätigst du, dass die aktuelle app.ini-Datei den korrekten SECRET_KEY enthält. reinstall_confirm_check_2=Die Repositorys und Einstellungen müssen eventuell neu synchronisiert werden. Durch das Ankreuzen dieses Kästchens bestätigst du, dass du die Hooks für die Repositorys und die authorized_keys-Datei manuell neu synchronisierst. Du bestätigst, dass du sicherstellst, dass die Repository- und Spiegeleinstellungen korrekt sind. reinstall_confirm_check_3=Du bestätigst, dass du absolut sicher bist, dass diese Forgejo mit der richtigen app.ini läuft, und du sicher bist, dass du neu installieren musst. Du bestätigst, dass du die oben genannten Risiken anerkennst. err_empty_db_path=Der SQLite3-Datenbankpfad darf nicht leer sein. @@ -257,7 +257,7 @@ err_admin_name_is_invalid=Administratornutzername ist ungültig general_title=Allgemeine Einstellungen app_name=Instanztitel -app_name_helper=Hier Ihren Instanznamen eingeben. Er wird auf jeder Seite angezeigt. +app_name_helper=Gib hier den Instanznamen ein. Er wird auf jeder Seite angezeigt. repo_path=Repository-Verzeichnis repo_path_helper=Remote-Git-Repositorys werden in diesem Verzeichnis gespeichert. lfs_path=Git-LFS-Wurzelpfad @@ -287,13 +287,13 @@ register_confirm=E-Mail-Bestätigung benötigt zum Registrieren mail_notify=E-Mail-Benachrichtigungen aktivieren server_service_title=Sonstige Server- und Drittserviceeinstellungen offline_mode=Offline-Modus aktivieren -offline_mode.description=Drittanbieter-CDNs deaktivieren und alle Ressourcen lokal bereitstellen. +offline_mode.description=Content Delivery Networks von Drittanbietern deaktivieren und alle Ressourcen lokal bereitstellen. disable_gravatar=Gravatar deaktivieren disable_gravatar.description=Gravatar und andere Drittanbieter-Avatar-Quellen deaktivieren. Ein Standardavatar wird verwendet, bis der Nutzer einen eigenen Avatar auf deren Instanz hochlädt. federated_avatar_lookup=Föderierte Profilbilder einschalten federated_avatar_lookup.description=Profilbilder mittels Libravatar suchen. disable_registration=Registrierung deaktivieren -disable_registration.description=Nur Instanz-Administratoren können neue Benutzerkonten anlegen. Es wird dazu geraten, die Registrierung deaktiviert zu lassen, außer wenn man eine öffentliche Instanz für alle hosten will und bereit ist, mit Spam-Accounts in großer Anzahl umzugehen. +disable_registration.description=Nur Instanz-Administratoren können neue Benutzerkonten anlegen. Es wird dazu geraten, die Registrierung deaktiviert zu lassen, außer wenn man eine öffentliche Instanz für alle hosten will und bereit ist, mit Spam-Konten in großer Anzahl umzugehen. allow_only_external_registration.description=Benutzer können nur über die konfigurierten externe Dienste neue Konten anlegen. openid_signin=OpenID-Anmeldung aktivieren openid_signin.description=Benutzeranmeldung via OpenID aktivieren. @@ -332,7 +332,7 @@ no_reply_address=Versteckte E-Mail-Domain no_reply_address_helper=Domain-Name für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername „Joe“ in Git als „joe@noreply.example.org“ protokolliert, wenn die versteckte E-Mail-Domain „noreply.example.org“ festgelegt ist. password_algorithm=Passwort-Hashing-Algorithmus invalid_password_algorithm=Ungültiger Passwort-Hash-Algorithmus -password_algorithm_helper=Lege einen Passwort-Hashing-Algorithmus fest. Algorithmen haben unterschiedliche Anforderungen und Stärken. Der argon2-Algorithmus ist ziemlich sicher, aber er verbraucht viel Speicher und kann für kleine Systeme ungeeignet sein. +password_algorithm_helper=Lege einen Passwort-Hashing-Algorithmus fest. Algorithmen haben unterschiedliche Anforderungen und Stärken. Der Argon2-Algorithmus ist ziemlich sicher, aber er verbraucht viel Speicher und kann für kleine Systeme ungeeignet sein. enable_update_checker=Aktualisierungsprüfung aktivieren env_config_keys=Umgebungskonfiguration env_config_keys_prompt=Die folgenden Umgebungsvariablen werden auch auf Ihre Konfigurationsdatei angewendet: @@ -385,26 +385,26 @@ remember_me=Dieses Gerät speichern forgot_password_title=Passwort vergessen forgot_password=Passwort vergessen? sign_up_successful=Konto wurde erfolgreich erstellt. Willkommen! -confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an %s gesendet. Um den Registrierungsprozess abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von: %s. Falls die E-Mail inkorrekt sein sollte, kannst du dich einloggen und anfragen, eine weitere Bestätigungs-E-Mail an eine andere Adresse zu senden. +confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an %s gesendet. Um den Registrierung abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von: %s. Falls die E-Mail inkorrekt sein sollte, kannst du dich einloggen und anfragen, eine weitere Bestätigungs-E-Mail an eine andere Adresse zu senden. must_change_password=Aktualisiere dein Passwort allow_password_change=Verlange vom Benutzer das Passwort zu ändern (empfohlen) -reset_password_mail_sent_prompt=Eine Bestätigungs-E-Mail wurde an %s gesendet. Um den Kontowiederherstellungsprozess abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von %s. +reset_password_mail_sent_prompt=Eine Bestätigungs-E-Mail wurde an %s gesendet. Um den Kontowiederherstellung abzuschließen, überprüfe bitte deinen Posteingang und folge dem angegebenen Link innerhalb von %s. active_your_account=Aktiviere dein Konto account_activated=Konto wurde aktiviert -prohibit_login=Der Account ist gesperrt -prohibit_login_desc=Dein Account ist auf dieser Instanz gesperrt worden. Bitte kontaktiere den Instanz-Administrator. +prohibit_login=Das Konto ist gesperrt +prohibit_login_desc=Dein Konto ist auf dieser Instanz gesperrt worden. Bitte kontaktiere den Instanz-Administrator. resent_limit_prompt=Du hast bereits eine Aktivierungs-E-Mail angefordert. Bitte warte 3 Minuten und probiere es dann nochmal. -has_unconfirmed_mail=Hallo %s, du hast eine unbestätigte E-Mail-Adresse (%s). Wenn du keine Bestätigungs-E-Mail erhalten hast oder eine neue senden möchtest, klicke bitte auf den folgenden Button. +has_unconfirmed_mail=Hallo, %s, du hast eine unbestätigte E-Mail-Adresse (%s). Wenn du keine Bestätigungs-E-Mail erhalten hast oder eine neue senden möchtest, klicke bitte auf den folgenden Button. resend_mail=Aktivierungs-E-Mail erneut verschicken send_reset_mail=Wiederherstellungs-E-Mail senden reset_password=Kontowiederherstellung invalid_code=Dein Bestätigungs-Code ist ungültig oder abgelaufen. invalid_code_forgot_password=Dein Bestätigungscode ist ungültig oder abgelaufen. Klicke hier, um eine neue Sitzung zu starten. -invalid_password=Ihr Passwort stimmt nicht mit dem Passwort überein, das zur Erstellung des Kontos verwendet wurde. +invalid_password=Dein Passwort stimmt nicht mit dem Passwort überein, das zur Erstellung des Kontos verwendet wurde. reset_password_helper=Konto wiederherstellen reset_password_wrong_user=Du bist angemeldet als %s, aber der Link zur Kontowiederherstellung ist für %s password_too_short=Das Passwort muss mindestens %d Zeichen lang sein. -non_local_account=Benutzer, die nicht von Forgejo verwaltet werden können ihre Passwörter nicht über das Web Interface ändern. +non_local_account=Benutzer, die nicht von Forgejo verwaltet werden, können ihre Passwörter nicht über das Web-Interface ändern. verify=Verifizieren scratch_code=Einmalpasswort use_scratch_code=Einmalpasswort verwenden @@ -423,9 +423,9 @@ oauth.signin.error.access_denied=Die Autorisierungsanfrage wurde abgelehnt. oauth.signin.error.temporarily_unavailable=Autorisierung fehlgeschlagen, da der Authentifizierungsserver vorübergehend nicht verfügbar ist. Bitte versuch es später erneut. openid_connect_submit=Verbinden openid_connect_title=Mit bestehendem Konto verbinden -openid_connect_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu. +openid_connect_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Konto zu. openid_register_title=Neues Konto einrichten -openid_register_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu. +openid_register_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Konto zu. openid_signin_desc=Gib deine OpenID-URI ein, zum Beispiel alice.openid.example.org oder https://openid.example.org/alice. disable_forgot_password_mail=Die Kontowiederherstellung ist deaktiviert, da keine E-Mail eingerichtet ist. Bitte kontaktiere den zuständigen Administrator. disable_forgot_password_mail_admin=Die Kontowiederherstellung ist nur verfügbar, wenn eine E-Mail eingerichtet wurde. Bitte richte eine E-Mail-Adresse ein, um die Kontowiederherstellung freizuschalten. @@ -433,11 +433,11 @@ email_domain_blacklisted=Du kannst dich nicht mit deiner E-Mail-Adresse registri authorize_application=Anwendung autorisieren authorize_redirect_notice=Du wirst zu %s weitergeleitet, wenn du diese Anwendung autorisierst. authorize_application_created_by=Diese Anwendung wurde von %s erstellt. -authorize_application_description=Wenn du diese Anwendung autorisierst, wird sie die Berechtigung erhalten, alle Informationen zu deinem Account zu bearbeiten oder zu lesen. Dies beinhaltet auch private Repositorys und Organisationen. -authorize_title=„%s“ den Zugriff auf deinen Account gestatten? +authorize_application_description=Wenn du diese Anwendung autorisierst, wird sie die Berechtigung erhalten, alle Informationen zu deinem Konto zu bearbeiten oder zu lesen. Dies beinhaltet auch private Repositorys und Organisationen. +authorize_title=„%s“ den Zugriff auf dein Konto gestatten? authorization_failed=Autorisierung fehlgeschlagen authorization_failed_desc=Die Autorisierung ist fehlgeschlagen, da wir eine ungültige Anfrage erkannt haben. Bitte kontaktiere den Betreuer der App, die du zu autorisieren versucht hast. -password_pwned=Das von dir gewählte Passwort befindet sich auf einer List gestohlener Passwörter, die öffentlich verfügbar sind. Bitte versuche es erneut mit einem anderen Passwort und ziehe in Erwägung, auch anderswo deine Passwörter zu ändern. +password_pwned=Das von dir gewählte Passwort befindet sich auf einer Liste gestohlener Passwörter, die öffentlich verfügbar sind. Bitte versuche es erneut mit einem anderen Passwort und ziehe in Erwägung, auch anderswo deine Passwörter zu ändern. password_pwned_err=Anfrage an HaveIBeenPwned konnte nicht abgeschlossen werden change_unconfirmed_email_summary = Ändern der E-Mail-Adresse, an die die Aktivierungsnachricht gesendet wird. change_unconfirmed_email_error = Ändern der E-Mail-Adresse fehlgeschlagen: %v @@ -448,14 +448,14 @@ back_to_sign_in = Zurück zur Anmeldung sign_in_openid = Mit OpenID fortfahren hint_login = Hast du bereits ein Konto? Jetzt anmelden! hint_register = Brauchst du ein Konto? Jetzt registrieren. -unauthorized_credentials = Die Zugangsdaten sind inkorrekt oder abgelaufen. Versuchen es erneut oder siehe %s für mehr Informationen -use_onetime_code = Einen One-Time-Code benutzen +unauthorized_credentials = Die Zugangsdaten sind inkorrekt oder abgelaufen. Versuche es erneut oder siehe %s für mehr Informationen +use_onetime_code = Einen Einmal-Code benutzen [mail] view_it_on=Auf %s ansehen reply=oder antworte direkt auf diese E-Mail link_not_working_do_paste=Link funktioniert nicht? Versuche, ihn zu kopieren und im Browser einzufügen. -hi_user_x=Hallo %s, +hi_user_x=Hallo, %s, activate_account=Bitte aktiviere dein Konto activate_account.text_1=Hallo %[1]s, danke für deine Registrierung bei %[2]s! @@ -467,7 +467,7 @@ activate_email.text=Bitte klicke innerhalb von %s auf folgenden Link, um register_notify=Willkommen bei %s register_notify.text_1=dies ist deine Bestätigungs-E-Mail für %s! register_notify.text_2=Du kannst dich mit dem Benutzernamen „%s“ anmelden -register_notify.text_3=Wenn jemand anderes diesen Account für dich erstellt hat, musst du zuerst dein Passwort setzen. +register_notify.text_3=Wenn jemand anderes dieses Konto für dich erstellt hat, musst du zuerst dein Passwort setzen. reset_password=Stelle dein Konto wieder her reset_password.text=Falls du das warst, klicke bitte innerhalb von %s auf folgenden Link, um dein Konto wiederherzustellen: @@ -516,24 +516,24 @@ admin.new_user.subject = Neuer Benutzer %s hat sich gerade angemeldet admin.new_user.user_info = Benutzerinformationen admin.new_user.text = Bitte hier klicken, um den Benutzer aus dem Admin-Panel zu verwalten. password_change.subject = Dein Passwort wurde geändert -password_change.text_1 = Das Passwort für deinen Account wurde soeben geändert. +password_change.text_1 = Das Passwort für dein Konto wurde soeben geändert. primary_mail_change.subject = Deine primäre E-Mail-Adresse wurde geändert totp_disabled.subject = TOTP wurde deaktiviert -totp_disabled.text_1 = TOTP (Time-based one-time password [zeitbasiertes Einmalpasswort]) wurde auf deinem Account soeben deaktiviert. -totp_disabled.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen. +totp_disabled.text_1 = TOTP (Time-based one-time password [zeitbasiertes Einmalpasswort]) wurde auf deinem Konto soeben deaktiviert. +totp_disabled.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in dein Konto mit 2FA einzuloggen. removed_security_key.subject = Ein Sicherheitsschlüssel wurde entfernt -removed_security_key.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in deinen Account mit 2FA einzuloggen. +removed_security_key.no_2fa = Es sind keine anderen 2FA-Methoden mehr konfiguriert, was bedeutet, dass es nicht mehr nötig ist, sich in dein Konto mit 2FA einzuloggen. account_security_caution.text_1 = Wenn du das warst, kannst du diese E-Mail bedenkenlos ignorieren. -removed_security_key.text_1 = Sicherheitsschlüssel „%[1]s“ wurde soeben von deinem Account entfernt. -primary_mail_change.text_1 = Die primäre E-Mail-Adresse deines Account wurde soeben zu %[1]s geändert. Das bedeutet, dass diese E-Mail-Adresse keine E-Mail-Benachrichtigungen für deinen Account erhalten wird. -account_security_caution.text_2 = Wenn du das nicht warst, wurde dein Account kompromittiert. Bitte kontaktiere die Admins dieser Webseite. +removed_security_key.text_1 = Sicherheitsschlüssel „%[1]s“ wurde soeben aus deinem Konto entfernt. +primary_mail_change.text_1 = Die primäre E-Mail-Adresse deines Kontos wurde soeben zu %[1]s geändert. Das bedeutet, dass diese E-Mail-Adresse keine E-Mail-Benachrichtigungen für dein Konto erhalten wird. +account_security_caution.text_2 = Wenn du das nicht warst, wurde dein Konto kompromittiert. Bitte kontaktiere die Admins dieser Webseite. totp_enrolled.subject = Du hast TOTP als 2FA-Methode aktiviert -totp_enrolled.text_1.has_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode oder einen deiner Sicherheitsschlüssel benutzen könntest. -totp_enrolled.text_1.no_webauthn = Du hast gerade eben TOTP für deinen Account aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in deinen Account TOTP als 2FA-Methode benutzen musst. +totp_enrolled.text_1.has_webauthn = Du hast gerade eben TOTP für dein Konto aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in dein Konto TOTP als 2FA-Methode oder einen deiner Sicherheitsschlüssel benutzen könntest. +totp_enrolled.text_1.no_webauthn = Du hast gerade eben TOTP für dein Konto aktiviert. Das bedeutet, dass du in Zukunft für alle Logins in dein Konto TOTP als 2FA-Methode benutzen musst. [modal] yes=Ja -no=Abbrechen +no=Nein confirm=Bestätigen cancel=Abbrechen modify=Aktualisieren @@ -568,7 +568,7 @@ url_error=`„%s“ ist keine gültige URL.` include_error=` muss den Text „%s“ enthalten.` glob_pattern_error=` Glob-Pattern ist ungültig: %s.` regex_pattern_error=` regex ist ungültig: %s.` -username_error=` darf nur alphanumerische Zeichen („0-9“, „a-z“, „A-Z“), Bindestriche („-“), Unterstriche („_“) und Punkte („.“) enthalten. Es kann nicht mit nicht-alphanumerischen Zeichen beginnen oder enden und aufeinanderfolgende nicht-alphanumerische Zeichen sind ebenfalls verboten.` +username_error=` darf nur alphanumerische Zeichen („0-9“, „a-z“, „A-Z“), Bindestriche („-“), Unterstriche („_“) und Punkte („.“) enthalten. Es darf nicht mit nicht-alphanumerischen Zeichen beginnen oder enden, und aufeinanderfolgende nicht-alphanumerische Zeichen sind ebenfalls verboten.` invalid_group_team_map_error=` Zuordnung ist ungültig: %s` unknown_error=Unbekannter Fehler: captcha_incorrect=Der eingegebene CAPTCHA-Code ist falsch. @@ -581,7 +581,7 @@ repo_name_been_taken=Der Repository-Name wird schon verwendet. repository_force_private=Privat erzwingen ist aktiviert: Private Repositorys können nicht veröffentlicht werden. repository_files_already_exist=Dateien für dieses Repository sind bereits vorhanden. Kontaktiere den Systemadministrator. repository_files_already_exist.adopt=Dateien für dieses Repository existieren bereits und können nur übernommen werden. -repository_files_already_exist.delete=Dateien für dieses Repository sind bereits vorhanden. Du must sie löschen. +repository_files_already_exist.delete=Dateien für dieses Repository sind bereits vorhanden. Du musst sie löschen. repository_files_already_exist.adopt_or_delete=Dateien für dieses Repository existieren bereits. Du musst sie entweder übernehmen oder löschen. visit_rate_limit=Die Ratenbegrenzung bei der Gegenseite wurde erreicht. 2fa_auth_required=Die Gegenseite benötigt Zweifaktorauthentifikation. @@ -597,7 +597,7 @@ password_lowercase_one=Mindestens ein Kleinbuchstabe password_uppercase_one=Mindestens ein Großbuchstabe password_digit_one=Mindestens eine Ziffer password_special_one=Mindestens ein Sonderzeichen (Satzzeichen, Klammern, Anführungszeichen, etc.) -enterred_invalid_repo_name=Der eingegebenen Repository-Name ist falsch. +enterred_invalid_repo_name=Der eingegebene Repository-Name ist falsch. enterred_invalid_org_name=Der eingegebene Organisationsname ist falsch. enterred_invalid_owner_name=Der Name des neuen Besitzers ist ungültig. enterred_invalid_password=Das eingegebene Passwort ist falsch. @@ -608,8 +608,8 @@ cannot_add_org_to_team=Eine Organisation kann nicht als Teammitglied hinzugefüg duplicate_invite_to_team=Der Benutzer wurde bereits als Teammitglied eingeladen. organization_leave_success=Du hast die Organisation %s erfolgreich verlassen. -invalid_ssh_key=Dein SSH-Key kann nicht überprüft werden: %s -invalid_gpg_key=Dein GPG-Key kann nicht überprüft werden: %s +invalid_ssh_key=Dein SSH-Schlüssel kann nicht überprüft werden: %s +invalid_gpg_key=Dein GPG-Schlüssel kann nicht überprüft werden: %s invalid_ssh_principal=Ungültige Identität: %s must_use_public_key=Der von dir bereitgestellte Schlüssel ist ein privater. Bitte lade deinen privaten Schlüssel nirgendwo hoch, sondern verwende stattdessen deinen öffentlichen. unable_verify_ssh_key=Der SSH-Schlüssel kann nicht verifiziert werden, überprüfe ihn auf Fehler. @@ -625,7 +625,7 @@ target_branch_not_exist=Der Ziel-Branch existiert nicht. username_error_no_dots = ` darf nur alphanumerische Zeichen („0-9“, „a-z“, „A-Z“), Bindestriche („-“), Unterstriche („_“) enthalten. Es kann nicht mit nicht-alphanumerischen Zeichen beginnen oder enden und aufeinanderfolgende nicht-alphanumerische Zeichen sind ebenfalls verboten.` admin_cannot_delete_self = Du kannst dich nicht selbst löschen, wenn du ein Admin bist. Bitte entferne zuerst deine Adminrechte. unset_password = Für den Benutzer ist das Passwort nicht gesetzt. -unsupported_login_type = Dieser Login-Typ unterstützt keine Accountlöschung. +unsupported_login_type = Dieser Login-Typ unterstützt keine Kontolöschung. required_prefix = Eingabe muss mit „%s“ anfangen Description = Beschreibung FullName = Vollständiger Name @@ -634,7 +634,7 @@ Biography = Biografie Website = Webseite Location = Ort To = Branchname -AccessToken = Zugangstoken +AccessToken = Zugriffstoken username_claiming_cooldown = Der Benutzername kann nicht beansprucht werden, weil seine Schutzzeit noch nicht vorbei ist. Er kann am %[1]s beansprucht werden. email_domain_is_not_allowed = Die Domain der E-Mail-Adresse des Benutzers %s steht in Konflikt mit EMAIL_DOMAIN_ALLOWLIST oder EMAIL_DOMAIN_BLOCKLIST. Bitte stelle sicher, dass du die E-Mail-Adresse richtig gesetzt hast. @@ -664,10 +664,10 @@ form.name_pattern_not_allowed=Das Muster „%s“ ist nicht in einem Benutzernam form.name_chars_not_allowed=Benutzername „%s“ enthält ungültige Zeichen. block_user = Benutzer blockieren block_user.detail = Bitte beachte, dass die Blockierung eines Benutzers auch andere Auswirkungen hat, so wie: -block_user.detail_2 = Dieser Benutzer wird nicht mehr nicht mit deinen Repositorys oder von dir erstellten Issues und Kommentaren interagieren können. -block_user.detail_1 = Ihr werdet euch nicht mehr gegenseitig folgen und könnt euch auch nicht mehr gegenseitig folgen. +block_user.detail_2 = Dieser Benutzer wird nicht mehr mit deinen Repositorys oder von dir erstellten Issues und Kommentaren interagieren können. +block_user.detail_1 = Ihr werdet euch nicht mehr gegenseitig folgen und es auch nicht mehr können. block = Blockieren -follow_blocked_user = Du kannst diesen Benutzer nicht folgen, weil du ihn blockiert hast, oder er dich blockiert hat. +follow_blocked_user = Du kannst diesem Benutzer nicht folgen, weil du ihn blockiert hast oder er dich blockiert hat. block_user.detail_3 = Ihr werdet nicht mehr in der Lage sein, euch gegenseitig als Repository-Mitarbeiter hinzuzufügen. unblock = Nicht mehr blockieren followers_one = %d Follower @@ -678,13 +678,13 @@ following.title.few = Folgt followers.title.one = Follower public_activity.visibility_hint.self_public = Deine Aktivität ist sichtbar für alle, außer für Interaktionen in privaten Räumen. Konfigurieren. public_activity.visibility_hint.admin_public = Diese Aktivität ist sichtbar für alle, aber als Administrator kannst du außerdem Interaktionen in privaten Räumen sehen. -public_activity.visibility_hint.self_private = Deine Aktivität ist nur sichtbar für dich und den Instanzadministratoren. Konfigurieren. +public_activity.visibility_hint.self_private = Deine Aktivität ist nur sichtbar für dich und die Instanzadministratoren. Konfigurieren. public_activity.visibility_hint.admin_private = Diese Aktivität ist sichtbar für dich, weil du ein Administrator bist, aber der Benutzer will sie privat halten. -public_activity.visibility_hint.self_private_profile = Deine Aktivität ist nur für dich und die Instanzadministratoren sichtbar, weil den Profil privat ist. Konfigurieren. +public_activity.visibility_hint.self_private_profile = Deine Aktivität ist nur für dich und die Instanzadministratoren sichtbar, weil dein Profil privat ist. Konfigurieren. [settings] profile=Profil -account=Account +account=Konto appearance=Erscheinung password=Passwort security=Sicherheit @@ -699,11 +699,11 @@ organization=Organisationen uid=UID webauthn=Zwei-Faktor-Authentifizierung (Sicherheitsschlüssel) -public_profile=Öffentliches profil +public_profile=Öffentliches Profil biography_placeholder=Erzähle anderen ein wenig über dich selbst! (Markdown wird unterstützt) location_placeholder=Teile deinen ungefähren Standort mit anderen profile_desc=Über dich -password_username_disabled=Benutzer, die nicht von Forgejo verwaltet werden können ihren Benutzernamen nicht ändern. Bitte kontaktiere deinen Administrator für mehr Details. +password_username_disabled=Benutzer, die nicht von Forgejo verwaltet werden, können ihren Benutzernamen nicht ändern. Bitte kontaktiere deinen Administrator für mehr Details. full_name=Vollständiger Name website=Webseite location=Standort @@ -714,7 +714,7 @@ update_language_not_found=Sprache „%s“ ist nicht verfügbar. update_language_success=Sprache wurde aktualisiert. update_profile_success=Dein Profil wurde aktualisiert. change_username=Dein Benutzername wurde geändert. -change_username_prompt=Hinweis: Das Ändern deines Benutzernamen ändert auch deine Account-URL. +change_username_prompt=Hinweis: Das Ändern deines Benutzernamens ändert auch deine Konto-URL. change_username_redirect_prompt=Der alte Benutzername wird auf den neuen Benutzernamen weiterleiten, bis er erneut als Benutzername verwendet wird. continue=Weiter cancel=Abbrechen @@ -741,7 +741,7 @@ comment_type_group_issue_ref=Issue-Referenz saved_successfully=Die Einstellungen wurden erfolgreich gespeichert. privacy=Datenschutz keep_activity_private=Aktivität auf der Profilseite ausblenden -lookup_avatar_by_mail=Profilbild anhand der E-Mail-Addresse suchen +lookup_avatar_by_mail=Profilbild anhand der E-Mail-Adresse suchen enable_custom_avatar=Benutzerdefiniertes Profilbild verwenden choose_new_avatar=Neues Profilbild auswählen update_avatar=Profilbild aktualisieren @@ -763,7 +763,7 @@ manage_emails=E-Mail-Adressen verwalten manage_themes=Standard-Theme manage_openid=OpenID-Adressen email_desc=Deine primäre E-Mail-Adresse wird für Benachrichtigungen, Passwort-Wiederherstellung und, sofern sie nicht versteckt ist, web-basierte Git-Operationen verwendet. -theme_desc=Dieses Thema wird für die Weboberfläche verwendet, wenn du angemeldet bist. +theme_desc=Dieses Theme wird für die Weboberfläche verwendet, wenn du angemeldet bist. primary=Primär activated=Aktiviert requires_activation=Erfordert Aktivierung @@ -773,7 +773,7 @@ activations_pending=Aktivierung ausstehend can_not_add_email_activations_pending=Es gibt eine ausstehende Aktivierung, versuche es in ein paar Minuten erneut, wenn du eine neue E-Mail hinzufügen möchtest. delete_email=Löschen email_deletion=E-Mail-Adresse entfernen -email_deletion_desc=Diese E-Mail-Adresse und die damit verbundenen Informationen werden von deinem Konto entfernt. Git-Commits von dieser E-Mail-Addresse bleiben unverändert. Fortfahren? +email_deletion_desc=Diese E-Mail-Adresse und die damit verbundenen Informationen werden von deinem Konto entfernt. Git-Commits von dieser E-Mail-Adresse bleiben unverändert. Fortfahren? email_deletion_success=Die E-Mail-Adresse wurde entfernt. theme_update_success=Deine Theme-Auswahl wurde gespeichert. theme_update_error=Das ausgewählte Theme existiert nicht. @@ -789,32 +789,32 @@ add_email_success=Die neue E-Mail-Addresse wurde hinzugefügt. email_preference_set_success=E-Mail-Einstellungen wurden erfolgreich aktualisiert. add_openid_success=Die neue OpenID-Adresse wurde hinzugefügt. keep_email_private=E-Mail-Adresse verbergen -keep_email_private_popup=Die E-Mail-Adresse wird nicht im Profil angezeigt und wird nicht der Standard für Commits über das Webinterface sein, wie zum Beispiel Dateiuploads, Bearbeitungen, und Merge-Commits. Stattdessen kann eine besondere Adresse %s benutzt werden, um Commits mit dem Benutzeraccount zu verbinden. Diese Option wirkt sich nicht auf bestehende Commits aus. +keep_email_private_popup=Die E-Mail-Adresse wird nicht im Profil angezeigt und wird nicht der Standard für Commits über das Webinterface sein, wie zum Beispiel Dateiuploads, Bearbeitungen und Merge-Commits. Stattdessen kann eine besondere Adresse %s benutzt werden, um Commits mit dem Benutzerkonto zu verbinden. Diese Option wirkt sich nicht auf bestehende Commits aus. openid_desc=Mit OpenID kannst du dich über einen Drittanbieter authentifizieren. manage_ssh_keys=SSH-Schlüssel verwalten manage_ssh_principals=SSH-Zertifikats-Principals verwalten manage_gpg_keys=GPG-Schlüssel verwalten add_key=Schlüssel hinzufügen -ssh_desc=Diese öffentlichen SSH-Schlüssel sind mit deinem Account verbunden. Der dazugehörigen privaten SSH-Schlüssel geben dir vollen Zugriff auf deine Repositorys. Verifizierte SSH-Schlüssel können verwendet werden, um SSH-signierte Git-Commits zu signieren. +ssh_desc=Diese öffentlichen SSH-Schlüssel sind mit deinem Konto verbunden. Die dazugehörigen privaten SSH-Schlüssel geben dir vollen Zugriff auf deine Repositorys. Verifizierte SSH-Schlüssel können verwendet werden, um SSH-signierte Git-Commits zu signieren. principal_desc=Diese SSH-Zertifikat-Principals sind mit deinem Konto verknüpft und erlauben den vollen Zugriff auf deine Repositorys. -gpg_desc=Diese öffentlichen GPG-Schlüssel sind mit deinem Account verbunden und werden benutzt, um deine Commits zu verifizieren. Halte die dazugehörigen privaten GPG-Schlüssel geheim, da diese deine Commits signieren. +gpg_desc=Diese öffentlichen GPG-Schlüssel sind mit deinem Konto verbunden und werden benutzt, um deine Commits zu verifizieren. Halte die dazugehörigen privaten GPG-Schlüssel geheim, da diese deine Commits signieren. ssh_helper=Brauchst du Hilfe? Sieh dir die Anleitung zum Erzeugen deiner eigenen SSH-Schlüssel an oder zum Lösen häufiger Probleme, denen du bei der Arbeit mit SSH begegnen kannst. gpg_helper=Brauchst du Hilfe? Sieh dir die Anleitung über GPG an. key_content_ssh_placeholder=Startet mit „ssh-ed25519“, „ssh-rsa“, „ecdsa-sha2-nistp256“, „ecdsa-sha2-nistp384“, „ecdsa-sha2-nistp521“, „sk-ecdsa-sha2-nistp256@openssh.com“ oder „sk-ssh-ed25519@openssh.com“ key_content_gpg_placeholder=Beginnt mit „-----BEGIN PGP PUBLIC KEY BLOCK-----“ add_new_principal=Identität hinzufügen -ssh_key_been_used=Dieser SSH-Key wird auf diesem Server bereits verwendet. +ssh_key_been_used=Dieser SSH-Schlüssel wird auf diesem Server bereits verwendet. ssh_key_name_used=Ein gleichnamiger SSH-Key existiert bereits in deinem Account. ssh_principal_been_used=Diese Identität ist bereits auf dem Server vorhanden. gpg_key_id_used=Ein öffentlicher GPG-Schlüssel mit der gleichen ID existiert bereits. -gpg_no_key_email_found=Dieser GPG-Key entspricht keiner mit deinem Account verbundenen aktivierten E-Mail-Addresse. Er kann trotzdem hinzugefügt werden, wenn du den gegebenen Token signierst. +gpg_no_key_email_found=Dieser GPG-Schlüssel entspricht keiner mit deinem Konto verbundenen aktivierten E-Mail-Adresse. Er kann trotzdem hinzugefügt werden, wenn du den gegebenen Token signierst. gpg_key_matched_identities=Passende Identitäten: gpg_key_matched_identities_long=Die eingebetteten Identitäten in diesem Schlüssel stimmen mit den folgenden aktivierten E-Mail-Adressen für diesen Benutzer überein. Commits, die mit diesen E-Mail-Addressen committed wurden, können mit diesem Schlüssel verifiziert werden. gpg_key_verified=Verifizierter Schlüssel gpg_key_verified_long=Der Schlüssel wurde mit einem Token verifiziert. Er kann verwendet werden, um Commits zu verifizieren, die mit irgendeiner für diesen Nutzer aktivierten E-Mail-Adresse und irgendeiner Identität dieses Schlüssels übereinstimmen. gpg_key_verify=Verifizieren -gpg_invalid_token_signature=Der GPG-Key, die Signatur und das Token stimmen nicht überein, oder das Token ist veraltet. +gpg_invalid_token_signature=Der GPG-Schlüssel, die Signatur und das Token stimmen nicht überein, oder das Token ist veraltet. gpg_token_required=Du musst eine Signatur für das folgende Token angeben gpg_token=Token gpg_token_help=Du kannst eine Signatur wie folgt generieren: @@ -825,12 +825,12 @@ ssh_key_verified=Verifizierter Schlüssel ssh_key_verified_long=Der Schlüssel wurde mit einem Token verifiziert. Er kann verwendet werden, um Commits zu verifizieren, die mit irgendeiner für diesen Nutzer aktivierten E-Mail-Adresse und irgendeiner Identität dieses Schlüssels übereinstimmen. ssh_key_verify=Verifizieren ssh_invalid_token_signature=Der gegebene SSH-Schlüssel, Signatur oder Token stimmen nicht überein oder der Token ist veraltet. -ssh_token_required=Sie müssen eine Signatur für das Token unten angeben +ssh_token_required=Du musst eine Signatur für das folgende Token angeben ssh_token=Token -ssh_token_help=Sie können eine Signatur wie folgt generieren: +ssh_token_help=Du kannst eine Signatur wie folgt generieren: ssh_token_signature=SSH-Textsignatur (armored signature) key_signature_ssh_placeholder=Beginnt mit „-----BEGIN SSH SIGNATURE-----“ -verify_ssh_key_success=SSH-Key „%s“ wurde verifiziert. +verify_ssh_key_success=SSH-Schlüssel „%s“ wurde verifiziert. subkeys=Unterschlüssel key_id=Schlüssel-ID key_name=Schlüsselname @@ -864,17 +864,17 @@ hide_openid=Nicht im Profil anzeigen ssh_disabled=SSH ist deaktiviert ssh_signonly=SSH ist derzeit deaktiviert, sodass diese Schlüssel nur zur Commit-Signaturverifizierung verwendet werden. ssh_externally_managed=Dieser SSH-Schlüssel wird extern für diesen Benutzer verwaltet -manage_access_token=Zugriffstokens +manage_access_token=Zugriffstoken generate_new_token=Neuen Token erzeugen -tokens_desc=Diese Tokens gewähren vollen Zugriff auf dein Konto mit der Forgejo-API. +tokens_desc=Diese Tokens gewähren vollen Zugriff auf dein Konto via Forgejo-API. token_name=Token-Name generate_token=Token generieren generate_token_success=Ein neuer Token wurde generiert. Kopiere diesen jetzt, da er nicht erneut angezeigt wird. generate_token_name_duplicate=%s wurde bereits als Anwendungsname verwendet. Bitte wähle einen neuen Namen. delete_token=Löschen access_token_deletion=Zugriffstoken löschen -access_token_deletion_desc=Wenn du ein Token löschst, haben die Anwendungen, die es nutzen, keinen Zugriff mehr auf deinen Account. Dies kann nicht rückgängig gemacht werden. Fortfahren? -delete_token_success=Der Zugriffstoken wurde gelöscht. Anwendungen die diesen Token genutzt haben, haben nun keinen Zugriff mehr auf deinen Account. +access_token_deletion_desc=Wenn du ein Token löschst, haben die Anwendungen, die es nutzen, keinen Zugriff mehr auf dein Konto. Dies kann nicht rückgängig gemacht werden. Fortfahren? +delete_token_success=Der Zugriffstoken wurde gelöscht. Anwendungen, die diesen Token genutzt haben, haben nun keinen Zugriff mehr auf dein Konto. repo_and_org_access=Repository- und Organisationszugriff permissions_public_only=Nur öffentlich permissions_access_all=Alle (öffentlich, privat und begrenzt) @@ -906,18 +906,18 @@ oauth2_regenerate_secret=Geheimnis neu generieren oauth2_regenerate_secret_hint=Geheimnis verloren? oauth2_client_secret_hint=Das Geheimnis wird nach dem Verlassen oder Aktualisieren dieser Seite nicht mehr angezeigt. Bitte stelle sicher, dass du es gespeichert hast. oauth2_application_edit=Bearbeiten -oauth2_application_create_description=OAuth2-Anwendungen geben deiner Drittanwendung Zugriff auf Benutzeraccounts dieser Forgejo-Instanz. -oauth2_application_remove_description=Das Entfernen einer OAuth2-Anwendung hat zur Folge, dass diese nicht mehr auf autorisierte Benutzeraccounts auf dieser Instanz zugreifen kann. Möchtest Du fortfahren? +oauth2_application_create_description=OAuth2-Anwendungen geben deiner Drittanwendung Zugriff auf Benutzerkonten dieser Forgejo-Instanz. +oauth2_application_remove_description=Das Entfernen einer OAuth2-Anwendung hat zur Folge, dass diese nicht mehr auf autorisierte Benutzerkonten auf dieser Instanz zugreifen kann. Möchtest du fortfahren? oauth2_application_locked=Wenn es in der Konfiguration aktiviert ist, registriert Forgejo einige OAuth2-Anwendungen beim Starten vor. Um unerwartetes Verhalten zu verhindern, können diese weder bearbeitet noch entfernt werden. Weitere Informationen findest Du in der OAuth2-Dokumentation. authorized_oauth2_applications=Autorisierte OAuth2-Anwendungen -authorized_oauth2_applications_description=Den folgenden Drittanbieter-Apps hast du Zugriff auf deinen persönlichen Forgejo-Account gewährt. Bitte widerrufe die Autorisierung für Apps, die nicht länger verwendet werden. +authorized_oauth2_applications_description=Den folgenden Drittanbieter-Apps hast du Zugriff auf dein persönliches Forgejo-Konto gewährt. Bitte widerrufe die Autorisierung für Apps, die nicht länger verwendet werden. revoke_key=Widerrufen revoke_oauth2_grant=Autorisierung widerrufen revoke_oauth2_grant_description=Wenn du die Autorisierung widerrufst, kann die Anwendung nicht mehr auf deine Daten zugreifen. Bist du dir sicher? revoke_oauth2_grant_success=Zugriff erfolgreich widerrufen. -twofa_desc=Um dein Konto gegen Passwortdiebstahl zu schützen, kannst du eine Smartphone oder ein anderes Gerät verwenden, um zeitbasierte Einmalpasswörter („TOTP“) zu erhalten. +twofa_desc=Um dein Konto gegen Passwortdiebstahl zu schützen, kannst du ein Smartphone oder ein anderes Gerät verwenden, um zeitbasierte Einmalpasswörter („TOTP“) zu erhalten. twofa_is_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung eingeschaltet. twofa_not_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung momentan nicht eingeschaltet. twofa_disable=Zwei-Faktor-Authentifizierung deaktivieren @@ -926,7 +926,7 @@ twofa_scratch_token_regenerated=Dein einmalig verwendbarer Wiederherstellungssch twofa_enroll=Zwei-Faktor-Authentifizierung aktivieren twofa_disable_note=Du kannst die Zwei-Faktor-Authentifizierung auch wieder deaktivieren. twofa_disable_desc=Wenn du die Zwei-Faktor-Authentifizierung deaktivierst, wird die Sicherheit deines Kontos verringert. Fortfahren? -regenerate_scratch_token_desc=Wenn du deinen Wiederherstellungsschlüssel verlegst oder es bereits benutzt hast, kannst du es hier zurücksetzen. +regenerate_scratch_token_desc=Wenn du deinen Wiederherstellungsschlüssel verlegst oder ihn bereits benutzt hast, kannst du ihn hier zurücksetzen. twofa_disabled=Zwei-Faktor-Authentifizierung wurde deaktiviert. scan_this_image=Scanne diese Grafik mit deiner Authentifizierungs-App: or_enter_secret=Oder gib das Geheimnis ein: %s @@ -935,18 +935,18 @@ passcode_invalid=Die PIN ist falsch. Probiere es erneut. twofa_enrolled=Die Zwei-Faktor-Authentifizierung wurde für dein Konto aktiviert. Bewahre deinen einmalig verwendbaren Wiederherstellungsschlüssel (%s) an einem sicheren Ort auf, da er nicht wieder angezeigt werden wird. twofa_failed_get_secret=Fehler beim Abrufen des Geheimnisses. -webauthn_desc=Sicherheitsschlüssel sind Geräte, die kryptografische Schlüssel beeinhalten. Diese können für die Zwei-Faktor-Authentifizierung verwendet werden. Der Sicherheitsschlüssel muss den Standard „WebAuthn“ unterstützen. +webauthn_desc=Sicherheitsschlüssel sind Geräte, die kryptografische Schlüssel beinhalten. Diese können für die Zwei-Faktor-Authentifizierung verwendet werden. Der Sicherheitsschlüssel muss den Standard „WebAuthn“ unterstützen. webauthn_register_key=Sicherheitsschlüssel hinzufügen webauthn_nickname=Nickname webauthn_delete_key=Sicherheitsschlüssel entfernen webauthn_delete_key_desc=Wenn du einen Sicherheitsschlüssel entfernst, kannst du dich nicht mehr mit ihm anmelden. Fortfahren? -manage_account_links=Verknüpfte Accounts -manage_account_links_desc=Diese externen Accounts sind mit deinem Forgejo-Account verknüpft. -link_account=Account verbinden -remove_account_link=Verknüpften Account entfernen -remove_account_link_desc=Wenn du den verknüpften Account entfernst, wirst du darüber nicht mehr auf deinen Forgejo-Account zugreifen können. Fortfahren? -remove_account_link_success=Der verknüpfte Account wurde entfernt. +manage_account_links=Verknüpfte Konten +manage_account_links_desc=Diese externen Konten sind mit deinem Forgejo-Konto verknüpft. +link_account=Konto verbinden +remove_account_link=Verknüpftes Konto entfernen +remove_account_link_desc=Wenn du das verknüpfte Konto entfernst, wirst du darüber nicht mehr auf dein Forgejo-Konto zugreifen können. Fortfahren? +remove_account_link_success=Das verknüpfte Konto wurde entfernt. hooks.desc=Webhooks hinzufügen, die für alle Repositorys, die dir gehören, ausgelöst werden. @@ -954,11 +954,11 @@ orgs_none=Du bist kein Mitglied in einer Organisation. repos_none=Du besitzt keine Repositorys. delete_account=Konto löschen -delete_prompt=Wenn du fortfährst, wird dein Account permanent gelöscht. Dies KANN NICHT rückgängig gemacht werden. -delete_with_all_comments=Dein Account existiert seit weniger als %s. Um Geisterkommentare zu vermeiden, werden alle deine Issue/PR-Kommentare gelöscht. +delete_prompt=Wenn du fortfährst, wird dein Konto permanent gelöscht. Dies KANN NICHT rückgängig gemacht werden. +delete_with_all_comments=Dein Konto existiert seit weniger als %s. Um Geisterkommentare zu vermeiden, werden alle deine Issue/PR-Kommentare gelöscht. confirm_delete_account=Löschen bestätigen delete_account_title=Benutzerkonto löschen -delete_account_desc=Bist du sicher, dass du diesen Account dauerhaft löschen möchtest? +delete_account_desc=Bist du sicher, dass du dieses Konto dauerhaft löschen möchtest? email_notifications.enable=E-Mail-Benachrichtigungen aktivieren email_notifications.onmention=Nur E-Mail bei Erwähnung @@ -974,7 +974,7 @@ visibility.limited_tooltip=Nur für angemeldete Benutzer sichtbar visibility.private=Privat visibility.private_tooltip=Sichtbar nur für Mitglieder von Organisationen, denen du beigetreten bist user_block_success = Dieser Benutzer wurde erfolgreich blockiert. -twofa_recovery_tip = Falls du dein Gerät verlierst, wirst du in der Lage sein, einen einmalig verwendbaren Wiederherstellungsschlüssel zu verwenden, um den auf dein Konto wiederherzustellen. +twofa_recovery_tip = Falls du dein Gerät verlierst, kannst du einen einmalig verwendbaren Wiederherstellungsschlüssel benutzen, um den Zugriff auf dein Konto wiederherzustellen. webauthn_alternative_tip = Du möchtest vielleicht eine zusätzliche Authentifizierungsmethode einrichten. blocked_users_none = Keine Benutzer blockiert. webauthn_key_loss_warning = Falls du deine Sicherheitsschlüssel verlierst, wirst du Zugang zu deinem Konto verlieren. @@ -990,16 +990,16 @@ additional_repo_units_hint_description = Einen „Mehr aktivieren“-Hinweis fü pronouns = Pronomen pronouns_unspecified = Nicht spezifiziert language.title = Standardsprache -keep_activity_private.description = Deine öffentliche Aktivität wird nur für dich selbst und die Instanzadminstratoren sichtbar sein. +keep_activity_private.description = Deine öffentliche Aktivität wird nur für dich selbst und die Instanzadministratoren sichtbar sein. language.localization_project = Hilf uns, Forgejo in deine Sprache zu übersetzen! Mehr erfahren. language.description = Diese Sprache wird in deinem Konto gespeichert und standardmäßig nach dem Anmelden benutzt. user_block_yourself = Du kannst dich nicht selbst blockieren. -change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen. -change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Benutzername während dieser Schutzzeit erneut beanspruchen. +change_username_redirect_prompt.with_cooldown.one = Der alte Benutzername ist nach einer Schutzzeit von einem Tag wieder für alle verfügbar. Du kannst den alten Benutzernamen während dieser Schutzzeit erneut beanspruchen. +change_username_redirect_prompt.with_cooldown.few = Der alte Benutzername ist nach einer Schutzzeit von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Benutzernamen während dieser Schutzzeit erneut beanspruchen. keep_pronouns_private = Pronomen nur angemeldeten Nutzern anzeigen keep_pronouns_private.description = Dies verbirgt deine Pronomen von Besuchern, die nicht angemeldet sind. quota.sizes.assets.artifacts = Artefakte -quota.applies_to_user = Die folgenden Quota-Regeln greifen für deinen Account +quota.applies_to_user = Die folgenden Quota-Regeln greifen für dein Konto quota.sizes.assets.attachments.issues = Issue-Anhänge quota.rule.exceeded.helper = Die Gesamtgröße der Objekte für diese Regel hat die Quota überschritten. storage_overview = Speicherübersicht @@ -1018,11 +1018,11 @@ quota.sizes.assets.all = Assets quota.sizes.assets.attachments.all = Anhänge quota.sizes.assets.packages.all = Pakete quota.sizes.wiki = Wiki -regenerate_token_success = Der Token wurde regeneriert. Anwendungen, die ihn benutzen, haben nicht länger Zugriff auf deinen Account und müssen mit dem neuen Token aktualisiert werden. -access_token_regeneration = Zugangstoken regenerieren -access_token_regeneration_desc = Einen Token zu regenerieren, wird den Zugriff auf deinen Account von Anwendungen, die ihn nutzen, zurückziehen. Dies kann nicht rückgängig gemacht werden. Fortsetzen? -regenerate_token = Regenerieren -ssh_token_help_ssh_agent = , oder, falls Sie einen SSH-Agenten benutzen (mit der Variable SSH_AUTH_SOCK gesetzt): +regenerate_token_success = Der Token wurde regeneriert. Anwendungen, die ihn benutzen, haben nicht länger Zugriff auf dein Konto und müssen mit dem neuen Token aktualisiert werden. +access_token_regeneration = Zugriffstoken neu generieren +access_token_regeneration_desc = Wenn du einen Token neu generierst, verlieren Anwendungen, die ihn nutzen, den Zugriff auf dein Konto. Dies kann nicht rückgängig gemacht werden. Fortfahren? +regenerate_token = Neu generieren +ssh_token_help_ssh_agent = , oder, falls du einen SSH-Agenten benutzt (mit der Variable SSH_AUTH_SOCK gesetzt): [repo] owner=Besitzer @@ -1058,12 +1058,12 @@ repo_desc=Beschreibung repo_desc_helper=Gib eine kurze Beschreibung an (optional) repo_lang=Sprache repo_gitignore_helper=Wähle .gitignore-Vorlagen aus -repo_gitignore_helper_desc=Wähle aus einer Liste an Vorlagen für bekannte Sprachen, welche Dateien ignoriert werden sollen. Typische Artefakte, die durch die Build-Tools der gewählten Sprache generiert werden, sind standardmäßig Bestandteil der .gitignore. +repo_gitignore_helper_desc=Wähle aus einer Liste an Vorlagen für bekannte Sprachen, welche Dateien ignoriert werden sollen. Typische Artefakte, die durch die Build-Werkzeuge der gewählten Sprache generiert werden, sind standardmäßig Bestandteil der .gitignore. issue_labels=Labels issue_labels_helper=Wähle eine Label-Sammlung license=Lizenz license_helper=Wähle eine Lizenz -license_helper_desc=Eine Lizenz regelt, was andere mit deinem Code tun (oder nicht tun) können. Unsicher, welche für dein Projekt die richtige ist? Siehe Choose a license. +license_helper_desc=Eine Lizenz regelt, was andere mit deinem Code tun (oder nicht tun) dürfen. Unsicher, welche für dein Projekt die richtige ist? Siehe Choose a license. readme=README readme_helper=Wähle eine README-Vorlage readme_helper_desc=Hier kannst du eine komplette Beschreibung für dein Projekt schreiben. @@ -1079,10 +1079,10 @@ mirror_interval_invalid=Das Spiegel-Intervall ist ungültig. mirror_sync_on_commit=Synchronisieren, wenn Commits gepusht wurden mirror_address=Klonen via URL mirror_address_desc=Gib alle erforderlichen Anmeldedaten im Abschnitt „Authentifizierung“ ein. -mirror_address_url_invalid=Die angegebene URL ist ungültig. Achte darauf, dass alle Komponenten der URL korrekt escaped wurden. +mirror_address_url_invalid=Die angegebene URL ist ungültig. Achte darauf, dass alle Komponenten der URL korrekt escapt wurden. mirror_address_protocol_invalid=Die angegebene URL ist ungültig. Nur Orte mit „http(s)://“ oder „git://“ können fürs Spiegeln benutzt werden. mirror_lfs=Großdatei-Speicher (LFS) -mirror_lfs_desc=Spiegeln von LFS-Dateien aktivieren. +mirror_lfs_desc=Spiegeln von LFS-Daten aktivieren. mirror_lfs_endpoint=LFS-Endpunkt mirror_lfs_endpoint_desc=Sync wird versuchen, die Klon-URL zu verwenden, um den LFS-Server zu bestimmen. Du kannst auch einen eigenen Endpunkt angeben, wenn die LFS-Dateien woanders gespeichert werden. mirror_last_synced=Zuletzt synchronisiert @@ -1139,9 +1139,9 @@ template.one_item=Es muss mindestens ein Vorlagenelement ausgewählt werden template.invalid=Es muss ein Vorlagen-Repository ausgewählt werden archive.title=Dieses Repository ist archiviert. Du kannst Dateien ansehen und es klonen, kannst aber seinen Status nicht verändern, zum Beispiel nichts pushen, keine Issues eröffnen und keine Pull-Requests oder Kommentare erstellen. -archive.title_date=Dieses Repository wurde am %s archiviert. Du kannst Dateien ansehen und es klonen, kannst aber seinen Status nicht verändern, zum Beispiel nichts pushen, und keine Issues eröffnen, oder Pull-Requests oder Kommentare erstellen. +archive.title_date=Dieses Repository wurde am %s archiviert. Du kannst Dateien ansehen und es klonen, kannst aber seinen Status nicht verändern, zum Beispiel nichts pushen, und keine Issues eröffnen oder Pull-Requests oder Kommentare erstellen. form.reach_limit_of_creation_1=Du hast bereits dein Limit von %d Repository erreicht. -form.reach_limit_of_creation_n=Du hast bereits dein Limit von %d Repositorys erreicht. +form.reach_limit_of_creation_n=Der Besitzer hat bereits das Limit von %d Repositorys erreicht. form.name_reserved=Der Repository-Name „%s“ ist reserviert. form.name_pattern_not_allowed=Das Muster „%s“ ist in Repository-Namen nicht erlaubt. @@ -1152,7 +1152,7 @@ migrate_options_lfs=LFS-Dateien migrieren migrate_options_lfs_endpoint.label=LFS-Endpunkt migrate_options_lfs_endpoint.description=Migration wird versuchen, über den entfernten Git-Server den LFS-Server zu bestimmen. Du kannst auch einen eigenen Endpunkt angeben, wenn die LFS-Dateien woanders gespeichert werden. migrate_options_lfs_endpoint.description.local=Ein lokaler Serverpfad wird ebenfalls unterstützt. -migrate_options_lfs_endpoint.placeholder=Wenn leer gelassen, wird der Endpunkt von der Clone-URL abgeleitet +migrate_options_lfs_endpoint.placeholder=Wenn leer gelassen, wird der Endpunkt von der Klon-URL abgeleitet migrate_items=Migrationselemente migrate_items_wiki=Wiki migrate_items_milestones=Meilensteine @@ -1169,7 +1169,7 @@ migrate.clone_local_path=oder ein lokaler Serverpfad migrate.permission_denied=Du hast keine Berechtigung zum Importieren lokaler Repositorys. migrate.permission_denied_blocked=Du kannst von keinen nicht erlaubten Hosts importieren. Bitte fragen deinen Administrator, die Einstellungen ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS zu überprüfen. migrate.invalid_local_path=Der lokale Pfad ist ungültig. Er existiert nicht oder ist kein Verzeichnis. -migrate.invalid_lfs_endpoint=Der LFS-Endpunkt ist nicht gültig. +migrate.invalid_lfs_endpoint=Der LFS-Endpunkt ist ungültig. migrate.failed=Fehler bei der Migration: %v migrate.migrate_items_options=Zugangs-Token wird benötigt, um zusätzliche Elemente zu migrieren migrated_from=Migriert von %[2]s @@ -1236,12 +1236,12 @@ commit=Commit release=Release releases=Releases tag=Tag -released_this=hat releast +released_this=hat es veröffentlicht file.title=%s an %s file_raw=Originalformat file_history=Verlauf file_view_source=Quelltext anzeigen -file_view_rendered=Ansicht rendern +file_view_rendered=Gerendert anzeigen file_view_raw=Originalformat anzeigen file_permalink=Permalink file_too_large=Die Datei ist zu groß zum Anzeigen. @@ -1357,7 +1357,7 @@ commits.older=Älter commits.newer=Neuer commits.signed_by=Signiert von commits.signed_by_untrusted_user=Signiert von nicht vertrauenswürdigen Benutzern -commits.signed_by_untrusted_user_unmatched=Von einem nicht vertrauenswürdigen Benutzer, der nicht auf den Committer passt, signiert +commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdigem Benutzer, der nicht mit dem Committer übereinstimmt commits.gpg_key_id=GPG-Schlüssel-ID commits.ssh_key_fingerprint=SSH-Schlüssel-Fingerabdruck commits.view_path=An diesem Punkt im Verlauf anzeigen @@ -1368,7 +1368,7 @@ commit.revert-header=Setze zurück: %s commit.revert-content=Branch auswählen, der zurückgesetzt werden soll: commit.cherry-pick=Cherry-Pick commit.cherry-pick-header=Cherry-Picke: %s -commit.cherry-pick-content=Branch auswählen, zu dem das Ergebnis des Cherry-Picks angewendet werden soll: +commit.cherry-pick-content=Branch auswählen, auf dem ein Cherry-Pick durchgeführt werden soll: commitstatus.error=Fehler commitstatus.failure=Fehler @@ -1383,7 +1383,7 @@ projects.description_placeholder=Beschreibung projects.create=Projekt erstellen projects.title=Titel projects.new=Neues Projekt -projects.new_subheader=Koordiniere, verfolge und aktualisiere deine Arbeit an einem Ort, so dass Projekte transparent und planmäßig bleiben. +projects.new_subheader=Koordiniere, verfolge und aktualisiere deine Arbeit an einem Ort, so dass Projekte transparent und im Zeitplan bleiben. projects.create_success=Das Projekt „%s“ wurde erstellt. projects.deletion=Projekt löschen projects.deletion_desc=Das Löschen eines Projekts entfernt es von allen damit zusammenhängenden Issues. Fortfahren? @@ -1508,7 +1508,7 @@ issues.filter_sort=Sortieren issues.filter_sort.latest=Neueste issues.filter_sort.oldest=Älteste issues.filter_sort.recentupdate=Kürzlich aktualisiert -issues.filter_sort.leastupdate=Am Längsten nicht aktualisiert +issues.filter_sort.leastupdate=Am längsten nicht aktualisiert issues.filter_sort.mostcomment=Am meisten kommentiert issues.filter_sort.leastcomment=Am wenigsten kommentiert issues.filter_sort.nearduedate=Nächstes Fälligkeitsdatum @@ -1624,7 +1624,7 @@ issues.unlock_comment=hat diese Diskussion %s entsperrt issues.lock_confirm=Sperren issues.unlock_confirm=Entsperren issues.lock.notice_1=- Andere Nutzer können keine neuen Kommentare beisteuern. -issues.lock.notice_2=– Du und andere Mitarbeiter mit Zugriff auf dieses Repository können weiterhin für andere sichtbare Kommentare hinterlassen. +issues.lock.notice_2=- Du und andere Mitarbeiter mit Zugriff auf dieses Repository können weiterhin für andere sichtbare Kommentare hinterlassen. issues.lock.notice_3=- Du kannst die Diskussion jederzeit wieder entsperren. issues.unlock.notice_1=- Jeder wird wieder in der Lage sein, zu diesem Issue zu kommentieren. issues.unlock.notice_2=- Du kannst den Issue jederzeit wieder sperren. @@ -1669,7 +1669,7 @@ issues.due_date_added=hat %[2]s das Fälligkeitsdatum %[1]s hinzugefügt issues.due_date_modified=hat das Fälligkeitsdatum von %[2]s auf %[1]s %[3]s geändert issues.due_date_remove=hat %[2]s das Fälligkeitsdatum %[1]s entfernt issues.due_date_overdue=Überfällig -issues.due_date_invalid=Das Fälligkeitsdatum ist ungültig oder außerhalb des zulässigen Bereichs. Bitte verwende das Format „jjjj-mm-tt“. +issues.due_date_invalid=Das Fälligkeitsdatum ist ungültig oder außerhalb des zulässigen Bereichs. Bitte verwende das Format „JJJJ-MM-TT“. issues.dependency.title=Abhängigkeiten issues.dependency.issue_no_dependencies=Keine Abhängigkeiten gesetzt. issues.dependency.pr_no_dependencies=Keine Abhängigkeiten gesetzt. @@ -1745,7 +1745,7 @@ pulls.compare_changes=Neuer Pull-Request pulls.allow_edits_from_maintainers=Änderungen von Maintainern erlauben pulls.allow_edits_from_maintainers_desc=Nutzer mit Schreibzugriff auf den Basisbranch können auch auf diesen Branch pushen pulls.allow_edits_from_maintainers_err=Aktualisieren fehlgeschlagen -pulls.compare_changes_desc=Wähle den Zielbranch, in das zusammengeführt werden soll, und den Quellbranch, von dem gepullt werden soll, aus. +pulls.compare_changes_desc=Wähle den Zielbranch, in den zusammengeführt werden soll, und den Quellbranch, von dem gepullt werden soll, aus. pulls.has_viewed_file=Gesehen pulls.has_changed_since_last_review=Seit deiner letzten Sichtung geändert pulls.viewed_files_label=%[1]d / %[2]d Dateien betrachtet @@ -1788,14 +1788,14 @@ pulls.remove_prefix=Präfix „%s“ entfernen pulls.data_broken=Dieser Pull-Requests ist kaputt, da Fork-Informationen gelöscht wurden. pulls.files_conflicted=Dieser Pull-Request hat Änderungen, die Konflikte mit dem Ziel-Branch haben. pulls.is_checking=Die Merge-Konfliktprüfung läuft noch. Bitte aktualisiere die Seite in wenigen Augenblicken. -pulls.is_ancestor=Dieser Branch ist bereits im Zielbranch enthalten. Es existiert nichts zusammenzuführen. +pulls.is_ancestor=Dieser Branch ist bereits im Zielbranch enthalten. Es existiert nichts zum Zusammenführen. pulls.is_empty=Die Änderungen an diesem Branch sind bereits auf dem Zielbranch. Dies wird ein leerer Commit sein. pulls.required_status_check_failed=Einige erforderliche Prüfungen waren nicht erfolgreich. pulls.required_status_check_missing=Einige erforderliche Prüfungen fehlen. pulls.required_status_check_administrator=Als Administrator kannst du diesen Pull-Request weiterhin zusammenführen. pulls.blocked_by_approvals=Dieser Pull-Request hat noch nicht genügend Genehmigungen. %d von %d Genehmigungen erteilt. -pulls.blocked_by_rejection=Dieser Pull-Request hat Änderungen, die von einem offiziellen Prüfer angefragt wurden. -pulls.blocked_by_official_review_requests=Dieser Pull-Request ist blockiert, weil ihm die Genehmigung von einem oder mehreren offiziellen Prüfern fehlt. +pulls.blocked_by_rejection=Dieser Pull-Request hat Änderungen, die von einem offiziellen Sichter angefragt wurden. +pulls.blocked_by_official_review_requests=Dieser Pull-Request ist blockiert, weil ihm die Genehmigung von einem oder mehreren offiziellen Sichtern fehlt. pulls.blocked_by_outdated_branch=Dieser Pull-Request ist blockiert, da er veraltet ist. pulls.blocked_by_changed_protected_files_1=Dieser Pull-Request ist blockiert, weil er eine geschützte Datei ändert: pulls.blocked_by_changed_protected_files_n=Dieser Pull-Request ist blockiert, weil er geschützte Dateien ändert: @@ -1826,9 +1826,9 @@ pulls.merge_commit_id=Die Merge-Commit-ID pulls.require_signed_wont_sign=Der Branch erfordert einen signierten Commit, aber dieser Merge wird nicht signiert pulls.invalid_merge_option=Du kannst diese Merge-Option auf diesen Pull-Request nicht anwenden. -pulls.merge_conflict=Merge fehlgeschlagen: Beim Zusammenführen existierte ein Konflikt. Tipp: Probiere eine andere Strategie +pulls.merge_conflict=Merge fehlgeschlagen: Beim Zusammenführen ist ein Konflikt entstanden. Tipp: Probiere eine andere Strategie pulls.merge_conflict_summary=Fehlermeldung -pulls.rebase_conflict=Merge fehlgeschlagen: Es existierte ein Konflikt beim Rebasen des Commits: %[1]s. Tipp: Versuche eine andere Strategie +pulls.rebase_conflict=Merge fehlgeschlagen: Es ist ein Konflikt beim Rebasen des Commits entstanden: %[1]s. Tipp: Versuche eine andere Strategie pulls.rebase_conflict_summary=Fehlermeldung pulls.unrelated_histories=Merge fehlgeschlagen: Der Head des Merges und die Basis haben keinen gemeinsamen Verlauf. Tipp: Versuche eine andere Strategie pulls.merge_out_of_date=Merge fehlgeschlagen: Während des Zusammenführens wurde die Basis aktualisiert. Tipp: Versuche es erneut. @@ -1848,7 +1848,7 @@ pulls.status_checks_details=Details pulls.update_branch=Branch durch Merge aktualisieren pulls.update_branch_rebase=Branch durch Rebase aktualisieren pulls.update_branch_success=Branch-Aktualisierung erfolgreich -pulls.update_not_allowed=Du hast keine Berechtigung, den Branch zu updaten +pulls.update_not_allowed=Du hast keine Berechtigung, den Branch zu aktualisieren pulls.outdated_with_base_branch=Dieser Branch enthält nicht die neusten Commits des Basis-Branches pulls.close=Pull-Request schließen pulls.closed_at=`hat diesen Pull-Request %s geschlossen` @@ -1910,7 +1910,7 @@ signing.wont_sign.error=Es gab einen Fehler bei der Prüfung, ob der Commit sign signing.wont_sign.nokey=Diese Instanz hat keinen Schlüssel, um diesen Commit zu signieren. signing.wont_sign.never=Commits werden nie signiert. signing.wont_sign.always=Commits werden immer signiert. -signing.wont_sign.pubkey=Der Commit wird nicht signiert, da du keinen öffentlichen Schlüssel mit deinem Account verknüpft hast. +signing.wont_sign.pubkey=Der Commit wird nicht signiert, da du keinen öffentlichen Schlüssel mit deinem Konto verknüpft hast. signing.wont_sign.twofa=Du musst Zwei-Faktor-Authentifizierung aktivieren, damit Commits signiert werden. signing.wont_sign.parentsigned=Der Commit wird nicht signiert werden, da der vorherige Commit nicht signiert ist. signing.wont_sign.basesigned=Der Merge-Commit wird nicht signiert werden, da der Basis-Commit nicht signiert ist. @@ -2087,7 +2087,7 @@ settings.pulls.default_allow_edits_from_maintainers=Änderungen von Maintainern settings.releases_desc=Repository-Releases aktivieren settings.packages_desc=Repository-Paket-Registry aktivieren settings.projects_desc=Repository-Projekte aktivieren -settings.actions_desc=Aktiviere integrierte CI/CD-Pipelines mit Forgejo-Actions +settings.actions_desc=Integrierte CI/CD-Pipelines mit Forgejo-Actions aktivieren settings.admin_settings=Administratoreinstellungen settings.admin_enable_health_check=Repository-Health-Checks aktivieren (git fsck) settings.admin_code_indexer=Code-Indexer @@ -2133,9 +2133,9 @@ settings.trust_model.collaborator.long=Mitarbeiter: Vertraue Signaturen von Mita settings.trust_model.collaborator.desc=Gültige Signaturen von Mitarbeitern dieses Projekts werden als „vertrauenswürdig“ markiert (egal, ob sie mit dem Committer übereinstimmen oder nicht). Andernfalls werden gültige Signaturen als „nicht vertrauenswürdig“ markiert, falls die Signatur zum Committer passt, ansonsten werden sie als „nicht übereinstimmend“ markiert. settings.trust_model.committer=Committer settings.trust_model.committer.long=Committer: Vertraue Signaturen, die zu Committern passen (dies stimmt mit GitHub überein und zwingt signierte Commits von Forgejo dazu, Forgejo als Committer zu haben) -settings.trust_model.committer.desc=Gültige Signaturen werden nur dann als „vertrauenswürdig“ gekennzeichnet, wenn sie mit ihrem Committer übereinstimmen. Ansonsten werden sie als „nicht übereinstimmend“ markiert. Das führt dazu, dass Forgejo auf signierten Commits, bei denen der echte Committer als „Co-authored-by:“ oder „Co-committed-by:“ in der Beschreibung eingetragen wurde, als Committer gilt. Der Forgejo-Standard-Key muss zu einem Benutzer in der Datenbank passen. +settings.trust_model.committer.desc=Gültige Signaturen werden nur dann als „vertrauenswürdig“ gekennzeichnet, wenn sie mit ihrem Committer übereinstimmen. Ansonsten werden sie als „nicht übereinstimmend“ markiert. Das führt dazu, dass Forgejo auf signierten Commits, bei denen der echte Committer als „Co-authored-by:“ oder „Co-committed-by:“ in der Beschreibung eingetragen wurde, als Committer gilt. Der Forgejo-Standard-Schlüssel muss zu einem Benutzer in der Datenbank passen. settings.trust_model.collaboratorcommitter=Mitarbeiter+Committer -settings.trust_model.collaboratorcommitter.long=Mitarbeiter+Committer: Signaturen der Mitarbeiter vertrauen die mit dem Committer übereinstimmen +settings.trust_model.collaboratorcommitter.long=Mitarbeiter+Committer: Signaturen der Mitarbeiter vertrauen, die mit dem Committer übereinstimmen settings.trust_model.collaboratorcommitter.desc=Gültige Signaturen von Mitarbeitern dieses Projekts werden als „vertrauenswürdig“ markiert, wenn sie mit dem Committer übereinstimmen. Andernfalls werden gültige Signaturen als „nicht vertrauenswürdig“ markiert, wenn die Signatur mit dem Committer übereinstimmt. Ansonsten werden sie als „nicht übereinstimmend“ markiert. Dies zwingt Forgejo, als Committer bei signierten Commits mit dem echten Committer als „Co-Authored-By:“ und „Co-Committed-By:“ im Commit zu markieren. Der Standard-Forgejo-Schlüssel muss mit einem Benutzer in der Datenbank übereinstimmen. settings.wiki_delete=Wiki-Daten löschen settings.wiki_delete_desc=Das Löschen von Wiki-Daten kann nicht rückgängig gemacht werden. Bitte sei vorsichtig. @@ -2192,7 +2192,7 @@ settings.githook_edit_desc=Wenn ein Hook nicht aktiv ist, wird der Standardinhal settings.githook_name=Hook-Name settings.githook_content=Hook-Inhalt settings.update_githook=Hook aktualisieren -settings.add_webhook_desc=Forgejo sendet eine POST-Anfrage mit festgelegtem Content-Type an die Ziel-URL. Mehr Informationen findest du in der Anleitung zu Webhooks (Englisch). +settings.add_webhook_desc=Forgejo sendet eine POST-Anfrage mit festgelegtem Content-Type an die Ziel-URL. Mehr dazu in der Anleitung zu Webhooks (auf Englisch). settings.payload_url=Ziel-URL settings.http_method=HTTP-Methode settings.content_type=POST-Content-Type @@ -2254,7 +2254,7 @@ settings.event_pull_request_merge=Pull-Request-Merge settings.event_package=Paket settings.event_package_desc=Paket wurde in einem Repository erstellt oder gelöscht. settings.branch_filter=Branch-Filter -settings.branch_filter_desc=Positivliste für Branches für Push-, Erzeugungs- und Löschevents, als glob-Pattern beschrieben. Es werden Events für alle Branches gemeldet, falls das Pattern * ist oder falls es leer ist. Siehe die %[2]s-Dokumentation für die Syntax (Englisch). Beispiele: master, {master,release*}. +settings.branch_filter_desc=Positivliste für Branches für Push-, Erzeugungs- und Löschevents, als Glob-Muster beschrieben. Es werden Ereignisse für alle Branches gemeldet, falls das Muster * ist oder falls es leer ist. Siehe die %[2]s-Dokumentation für die Syntax (Englisch). Beispiele: master, {master,release*}. settings.authorization_header=Authorization-Header settings.authorization_header_desc=Wird, falls vorhanden, als Authorization-Header mitgesendet. Beispiele: %s. settings.active=Aktiv @@ -2286,20 +2286,20 @@ settings.web_hook_name_packagist=Packagist settings.packagist_username=Benutzername für Packagist settings.packagist_api_token=API-Token settings.packagist_package_url=Paket-URL -settings.deploy_keys=Deploy-Keys -settings.add_deploy_key=Deploy-Key hinzufügen -settings.deploy_key_desc=Deploy-Keys können Nur-Lese-Zugriff oder Lese- und Schreibzugriff auf das Repository haben. +settings.deploy_keys=Deploy-Schlüssel +settings.add_deploy_key=Deploy-Schlüssel hinzufügen +settings.deploy_key_desc=Deploy-Schlüssel können Nur-Lese-Zugriff oder Lese-und-Schreib-Zugriff auf das Repository haben. settings.is_writable=Erlaube Schreibzugriff settings.is_writable_info=Erlaube diesem Deploy-Key auf das Repository zu pushen. -settings.no_deploy_keys=Noch keine Deploy-Keys vorhanden. +settings.no_deploy_keys=Noch keine Deploy-Schlüssel vorhanden. settings.title=Titel settings.deploy_key_content=Inhalt -settings.key_been_used=Ein Deploy-Key mit identischem Inhalt wird bereits verwendet. -settings.key_name_used=Ein Deploy-Key mit diesem Namen existiert bereits. -settings.add_key_success=Der Deploy-Key „%s“ wurde erfolgreich hinzugefügt. -settings.deploy_key_deletion=Deploy-Key löschen -settings.deploy_key_deletion_desc=Nach dem Löschen wird dieser Deploy-Key keinen Zugriff mehr auf dieses Repository haben. Fortfahren? -settings.deploy_key_deletion_success=Der Deploy-Key wurde entfernt. +settings.key_been_used=Ein Deploy-Schlüssel mit identischem Inhalt wird bereits verwendet. +settings.key_name_used=Ein Deploy-Schlüssel mit diesem Namen existiert bereits. +settings.add_key_success=Der Deploy-Schlüssel „%s“ wurde erfolgreich hinzugefügt. +settings.deploy_key_deletion=Deploy-Schlüssel löschen +settings.deploy_key_deletion_desc=Nach dem Löschen wird dieser Deploy-Schlüssel keinen Zugriff mehr auf dieses Repository haben. Fortfahren? +settings.deploy_key_deletion_success=Der Deploy-Schlüssel wurde entfernt. settings.branches=Branches settings.protected_branch=Branch-Schutz settings.protected_branch.save_rule=Regel speichern @@ -2313,7 +2313,7 @@ settings.protect_enable_merge=Merge aktivieren settings.protect_enable_merge_desc=Jeder mit Schreibzugriff darf die Pull-Requests in diesen Branch zusammenführen. settings.protect_whitelist_committers=Positivlisten-eingeschränkter Push settings.protect_whitelist_committers_desc=Jeder, der auf der Whitelist steht, darf in diesen Branch pushen (aber kein Force-Push). -settings.protect_whitelist_deploy_keys=Deploy-Key mit Schreibzugriff zum Pushen whitelisten. +settings.protect_whitelist_deploy_keys=Deploy-Schlüssel mit Schreibzugriff zum Pushen auf die Positivliste setzen. settings.protect_whitelist_users=Nutzer, die pushen dürfen settings.protect_whitelist_teams=Teams, die pushen dürfen settings.protect_merge_whitelist_committers=Merge-Positivliste aktivieren @@ -2323,10 +2323,10 @@ settings.protect_merge_whitelist_teams=Teams, die zusammenführen dürfen settings.protect_check_status_contexts=Statusprüfung aktivieren settings.protect_status_check_patterns=Statuscheck-Muster settings.protect_status_check_patterns_desc=Gib Muster ein, um festzulegen, welche Statusüberprüfungen durchgeführt werden müssen, bevor Branches in einen Branch, der dieser Regel entspricht, zusammenführen werden können. Jede Zeile gibt ein Muster an. Muster dürfen nicht leer sein. -settings.protect_check_status_contexts_desc=Vor dem Zusammenführen müssen Statusprüfungen bestanden werden. Wähle aus, welche Statusprüfungen erfolgreich durchgeführt werden müssen, bevor Branches in einen anderen zusammengeführt werden können, der dieser Regel entspricht. Wenn aktiviert, müssen Commits zuerst auf einen anderen Branch gepusht werden, dann nach bestandener Statusprüfung gemergt oder direkt auf einen Branch gepusht werden, der dieser Regel entspricht. Wenn kein Kontext ausgewählt ist, muss der letzte Commit unabhängig vom Kontext erfolgreich sein. +settings.protect_check_status_contexts_desc=Vor dem Zusammenführen müssen Statusprüfungen bestanden werden. Wähle aus, welche Statusprüfungen erfolgreich durchgeführt werden müssen, bevor Branches in einen anderen zusammengeführt werden können, der dieser Regel entspricht. Wenn aktiviert, müssen Commits zuerst auf einen anderen Branch gepusht werden, dann nach bestandener Statusprüfung zusammengeführt oder direkt auf einen Branch gepusht werden, der dieser Regel entspricht. Wenn kein Kontext ausgewählt ist, muss der letzte Commit unabhängig vom Kontext erfolgreich sein. settings.protect_check_status_contexts_list=Statusprüfungen, die in der letzten Woche für dieses Repository gefunden wurden settings.protect_status_check_matched=Übereinstimmung -settings.protect_invalid_status_check_pattern=Ungültiges Statusprüfungspattern: „%s“. +settings.protect_invalid_status_check_pattern=Ungültiges Statusprüfungsmuster: „%s“. settings.protect_no_valid_status_check_patterns=Keine gültigen Statuscheck-Muster. settings.protect_required_approvals=Erforderliche Genehmigungen settings.protect_required_approvals_desc=Erlaube das Zusammenführen des Pull-Requests nur mit genügend positiven Sichtungen. @@ -2340,7 +2340,7 @@ settings.require_signed_commits=Signierte Commits erforderlich settings.require_signed_commits_desc=Pushes auf diesen Branch ablehnen, wenn Commits nicht signiert oder nicht überprüfbar sind. settings.protect_branch_name_pattern=Muster für geschützte Branchnamen settings.protect_patterns=Muster -settings.protect_protected_file_patterns=Geschützte Dateimuster (durch Semikolon „;“ getrennt) +settings.protect_protected_file_patterns=Muster für geschützte Dateien (durch Semikolon „;“ getrennt) settings.protect_protected_file_patterns_desc=Geschützte Dateien dürfen nicht direkt geändert werden, auch wenn der Benutzer Rechte hat, Dateien in diesem Branch hinzuzufügen, zu bearbeiten oder zu löschen. Mehrere Muster können mit Semikolon („;“) getrennt werden. Siehe %s-Dokumentation zur Mustersyntax. Beispiele: .drone.yml, /docs/**/*.txt. settings.protect_unprotected_file_patterns=Ungeschützte Dateimuster (durch Semikolon „;“ getrennt) settings.protect_unprotected_file_patterns_desc=Ungeschützte Dateien, die direkt geändert werden dürfen, wenn der Benutzer Schreibzugriff hat, können die Push-Beschränkung umgehen. Mehrere Muster können mit Semikolon („;“) getrennt werden. Siehe %[2]s-Dokumentation zur Mustersyntax. Beispiele: .drone.yml, /docs/**/*.txt. @@ -2350,13 +2350,13 @@ settings.remove_protected_branch_failed=Entfernen der Branchschutzregel „%s“ settings.protected_branch_deletion=Branch-Schutz löschen settings.protected_branch_deletion_desc=Wenn du den Branch-Schutz deaktivierst, können alle Nutzer mit Schreibrechten auf den Branch pushen. Fortfahren? settings.block_rejected_reviews=Zusammenführung bei abgelehnten Sichtungen blockieren -settings.block_rejected_reviews_desc=Merge ist nicht möglich, wenn Änderungen durch offizielle Prüfer angefragt werden, auch wenn genügend Genehmigungen existieren. +settings.block_rejected_reviews_desc=Zusammenführen ist nicht möglich, wenn Änderungen durch offizielle Prüfer angefragt werden, auch wenn genügend Genehmigungen existieren. settings.block_on_official_review_requests=Merge bei offiziellen Sichtungsanfragen blockieren -settings.block_on_official_review_requests_desc=Merge ist nicht möglich, wenn offizielle Sichtungsanfrangen vorliegen, selbst wenn genügend Genehmigungen existieren. +settings.block_on_official_review_requests_desc=Merge ist nicht möglich, wenn offizielle Sichtungsanfragen vorliegen, selbst wenn genügend Genehmigungen existieren. settings.block_outdated_branch=Merge blockieren, wenn der Pull-Request veraltet ist settings.block_outdated_branch_desc=Merge ist nicht möglich, wenn der Head-Branch hinter dem Basis-Branch ist. settings.default_branch_desc=Wähle einen Standardbranch für Pull-Requests und Code-Commits: -settings.merge_style_desc=Merge-Styles +settings.merge_style_desc=Merge-Stile settings.default_merge_style_desc=Standard-Mergeverhalten settings.choose_branch=Branch wählen … settings.no_protected_branch=Es gibt keine geschützten Branches. @@ -2373,7 +2373,7 @@ settings.tags.protection.allowed.teams=Erlaubte Teams settings.tags.protection.allowed.noone=Niemand settings.tags.protection.create=Regel hinzufügen settings.tags.protection.none=Es gibt keine geschützten Tags. -settings.tags.protection.pattern.description=Du kannst einen einzigen Namen oder ein globales Schema oder einen regulären Ausdruck verwenden, um mehrere Tags zu schützen. Mehr dazu im Guide für geschützte Tags (Englisch). +settings.tags.protection.pattern.description=Du kannst einen einzigen Namen oder ein globales Schema oder einen regulären Ausdruck verwenden, um mehrere Tags zu schützen. Mehr dazu in der Anleitung für geschützte Tags (auf Englisch). settings.bot_token=Bot-Token settings.chat_id=Chat-ID settings.thread_id=Thread-ID @@ -2386,8 +2386,8 @@ settings.archive.text=Durch das Archivieren wird ein Repo vollständig schreibge settings.archive.success=Das Repo wurde erfolgreich archiviert. settings.archive.error=Beim Versuch, das Repository zu archivieren, ist ein Fehler aufgetreten. Weitere Details finden sich im Log. settings.archive.error_ismirror=Du kannst kein gespiegeltes Repo archivieren. -settings.archive.branchsettings_unavailable=Branch-Einstellungen sind nicht verfügbar in archivierten Repos. -settings.archive.tagsettings_unavailable=Tag-Einstellungen sind nicht verfügbar in archivierten Repos. +settings.archive.branchsettings_unavailable=In archivierten Repos sind Branch-Einstellungen nicht verfügbar. +settings.archive.tagsettings_unavailable=In archivierten Repos sind Tag-Einstellungen nicht verfügbar. settings.unarchive.button=Archivierung zurücksetzen settings.unarchive.header=Archivierung dieses Repositorys zurücksetzen settings.unarchive.text=Durch das Aufheben der Archivierung kann das Repo wieder Commits und Pushes sowie neue Issues und Pull-Requests empfangen. @@ -2555,7 +2555,7 @@ branch.included=Enthalten branch.create_new_branch=Branch aus Branch erstellen: branch.confirm_create_branch=Branch erstellen branch.warning_rename_default_branch=Du benennst den Standard-Branch um. -branch.rename_branch_to=Umbenennung des Zweigs "%s". +branch.rename_branch_to=Branch "%s" wird umbenannt. branch.create_branch_operation=Branch erstellen branch.new_branch=Neue Branch erstellen branch.new_branch_from=Neuen Branch von „%s“ erstellen @@ -2592,7 +2592,7 @@ settings.add_collaborator_blocked_them = Der Mitarbeiter konnte nicht hinzugefü settings.wiki_rename_branch_main = Den Wiki-Branch-Namen normalisieren settings.enter_repo_name = Gib den Besitzer- und den Repository-Namen genau wie angezeigt ein: settings.wiki_branch_rename_success = Der Branch-Name des Repository-Wikis wurde erfolgreich normalisiert. -settings.archive.mirrors_unavailable = Spiegel sind nicht verfügbar in archivierten Repos. +settings.archive.mirrors_unavailable = In archivierten Repos sind Spiegel nicht verfügbar. pulls.blocked_by_user = Du kannst keinen Pull-Request in diesem Repository erstellen, weil du vom Repository-Besitzer blockiert wurdest. settings.add_collaborator_blocked_our = Der Mitarbeiter konnte nicht hinzugefügt werden, weil der Repository-Besitzer ihn blockiert hat. issues.blocked_by_user = Du kannst keine Issues in diesem Repository erstellen, weil du vom Repository-Besitzer blockiert wurdest. @@ -2615,7 +2615,7 @@ pulls.cmd_instruction_hint = Anweisungen für die Kommandozeile betrachten pulls.cmd_instruction_checkout_title = Auschecken wiki.cancel = Abbrechen settings.wiki_globally_editable = Allen erlauben, das Wiki zu bearbeiten -settings.protect_branch_name_pattern_desc = Geschützte Branch-Namens-Patterns. Siehe die Dokumentation für Pattern-Syntax. Beispiele: main, release/** +settings.protect_branch_name_pattern_desc = Namensmuster für geschützte Branches. Siehe die Dokumentation für Mustersyntax. Beispiele: main, release/** settings.ignore_stale_approvals = Abgestandene Genehmigungen ignorieren settings.ignore_stale_approvals_desc = Genehmigungen, welche für ältere Commits gemacht wurden (abgestandene Sichtungen), nicht in die Gesamtzahl der Genehmigung des PRs mitzählen. Irrelevant, falls abgestandene Sichtungen bereits verworfen werden. pulls.commit_ref_at = `referenzierte diesen Pull-Request aus einem Commit %s` @@ -2628,7 +2628,7 @@ settings.units.overview = Übersicht settings.wiki_rename_branch_main_notices_1 = Diese Aktion KANN NICHT rückgängig gemacht werden. settings.wiki_rename_branch_main_notices_2 = Dies wird den internen Branch des Repository-Wikis von %s permanent umbenennen. Existierende Checkouts müssen aktualisiert werden. settings.wiki_branch_rename_failure = Der Branch-Name des Repository-Wiki konnte nicht normalisiert werden. -settings.confirm_wiki_branch_rename = Den Wiki-Branch umbenenennen +settings.confirm_wiki_branch_rename = Den Wiki-Branch umbenennen activity.navbar.contributors = Mitwirkende contributors.contribution_type.deletions = Löschungen contributors.contribution_type.additions = Einfügungen @@ -2665,7 +2665,7 @@ settings.add_webhook.invalid_path = Der Pfad darf kein „.“ oder „..“ enh settings.sourcehut_builds.manifest_path = Build-Manifest-Pfad settings.sourcehut_builds.visibility = Job-Sichtbarkeit settings.sourcehut_builds.secrets = Geheimnisse -settings.sourcehut_builds.secrets_helper = Dem Job zugriff auf die Build-Geheimnisse geben (benötigt die SECRETS:RO-Berechtigung) +settings.sourcehut_builds.secrets_helper = Dem Job Zugriff auf die Build-Geheimnisse geben (benötigt die SECRETS:RO-Berechtigung) settings.web_hook_name_sourcehut_builds = SourceHut-Builds settings.graphql_url = GraphQL-URL settings.matrix.room_id_helper = Die Raum-ID kann über den Element-Webclient ermittelt werden: Raumeinstellungen > erweitert > interne Raum-ID. Beispielsweise %s. @@ -2685,11 +2685,11 @@ settings.federation_following_repos = URLs folgender Repositorys. Durch „;“ settings.federation_not_enabled = Föderation ist auf deiner Instanz nicht aktiviert. settings.federation_apapiurl = Föderations-URL dieses Repositorys. Kopiere sie und füge sie in die Föderationseinstellungen eines anderen Repositorys als URL eines folgenden Repositorys ein. project = Projekte -comments.edit.already_changed = Die Änderungen an diesem Kommentar können nicht gespeichert werden. Es scheint, als seien die Inhalte bereits durch einen anderen Benutzer verändert worden. Bitte die Seite neu laden und das Bearbeiten erneut versuchen, um deren Änderungen nicht zu überschreiben +comments.edit.already_changed = Die Änderungen an diesem Kommentar können nicht gespeichert werden. Es scheint, als seien die Inhalte bereits durch einen anderen Benutzer verändert worden. Bitte die Seite neu laden und das Bearbeiten erneut versuchen, um dessen Änderungen nicht zu überschreiben issues.edit.already_changed = Die Änderungen an diesem Issue können nicht gespeichert werden. Es scheint, als seien die Inhalte bereits durch einen anderen Benutzer verändert worden. Bitte die Seite neu laden und das Bearbeiten erneut versuchen, um deren Änderungen nicht zu überschreiben -pulls.edit.already_changed = Die Änderungen an diesem Pull-Request können nicht gespeichert werden. Es scheint, als seien die Inhalte bereits durch einen anderen Benutzer verändert worden. Bitte die Seite neu laden und das Bearbeiten erneut versuchen, um deren Änderungen nicht zu überschreiben -subscribe.pull.guest.tooltip = Einloggen, um diesen Pull-Request zu abbonieren. -subscribe.issue.guest.tooltip = Einloggen, um dieses Issue zu abbonieren. +pulls.edit.already_changed = Die Änderungen an diesem Pull-Request können nicht gespeichert werden. Es scheint, als seien die Inhalte bereits durch einen anderen Benutzer verändert worden. Bitte die Seite neu laden und das Bearbeiten erneut versuchen, um dessen Änderungen nicht zu überschreiben +subscribe.pull.guest.tooltip = Anmelden, um diesen Pull-Request zu abonnieren. +subscribe.issue.guest.tooltip = Anmelden, um dieses Issue zu abonnieren. issues.author.tooltip.pr = Dieser Benutzer ist der Autor dieses Pull-Requests. issues.author.tooltip.issue = Dieser Benutzer ist der Autor dieses Issues. activity.commit = Commit-Aktivität @@ -2702,8 +2702,8 @@ release.add_external_asset = Externes Asset hinzufügen release.invalid_external_url = Ungültige externe URL: „%s“ activity.published_prerelease_label = Pre-Release activity.published_tag_label = Tag -settings.pull_mirror_sync_quota_exceeded = Quota überschritten, Änderungen werden nicht gepullt. -settings.transfer_quota_exceeded = Der neue Eigentümer (%s) hat die Quota überschritten. Das Repository wurde nicht übertragen. +settings.pull_mirror_sync_quota_exceeded = Kontingent überschritten, Änderungen werden nicht gepullt. +settings.transfer_quota_exceeded = Der neue Eigentümer (%s) hat das Kontingent überschritten. Das Repository wurde nicht übertragen. no_eol.text = Kein EOL no_eol.tooltip = Diese Datei enthält am Ende kein Zeilenende-Zeichen (EOL). pulls.cmd_instruction_merge_warning = Achtung: Die Einstellung „Autoerkennung von manuellen Zusammenführungen“ ist für dieses Repository nicht aktiviert. Du musst hinterher diesen Pull-Request als manuell zusammengeführt markieren. @@ -2732,7 +2732,7 @@ issues.num_reviews_one = %d Sichtung issues.summary_card_alt = Zusammenfassung eines Issues mit dem Titel „%s“ im Repository %s issues.num_reviews_few = %d Sichtungen editor.add_tmpl.filename = Dateiname -settings.default_update_style_desc = Standard-Aktualisierungsart um Pull-Requests zu aktualisieren, die hinter dem Base-Branch sind. +settings.default_update_style_desc = Standard-Aktualisierungsart, um Pull-Requests zu aktualisieren, die hinter dem Base-Branch sind. new_advanced = Erweiterte Einstellungen new_advanced_expand = Zum Ausklappen klicken pulls.sign_in_require = Anmelden, um einen neuen Pull-Request zu erstellen. @@ -2745,7 +2745,7 @@ issues.reaction.alt_many = %[1]s und %[2]d mehr reagierten %[3]s. issues.reaction.alt_few = %[1]s reagierten %[2]s. issues.reaction.alt_add = Füge %[1]s Reaktion zum Kommentar hinzu. issues.reaction.alt_remove = Entferne %[1]s Reaktion von diesem Kommentar. -summary_card_alt = Zusammenfassungskarte des Repositorys %s +summary_card_alt = Übersichtskarte des Repositorys %s release.summary_card_alt = Übersichtskarte eines Releases mit dem Titel „%s“ im Repository %s archive.pull.noreview = Dieses Repository ist archiviert. Pull-Requests können nicht überprüft werden. editor.commit_email = Commit-E-Mail @@ -2758,10 +2758,10 @@ issues.filter_no_results_placeholder = Versuche, deine Suchfilter anzupassen. migrate.repo_desc_helper = Leer lassen, um vorhandene Beschreibung zu importieren archive.nocomment = Kommentieren ist nicht möglich, da das Repository archiviert ist. comment.blocked_by_user = Kommentieren ist nicht möglich, da du vom Repository-Besitzer oder vom Autor blockiert wurdest. -sync_fork.branch_behind_one = Dieser Branch ist %[1]d Commit hinter %[2]s -sync_fork.branch_behind_few = Dieser Branch ist %[1]d Commits hinter %[2]s +sync_fork.branch_behind_one = Dieser Branch hinkt %[1]d Commit hinter %[2]s +sync_fork.branch_behind_few = Dieser Branch hinkt %[1]d Commits hinter %[2]s sync_fork.button = Sync -settings.event_action_failure_desc = Action-Run endete im Fehlschlag. +settings.event_action_failure_desc = Action-Run ist fehlgeschlagen. settings.event_action_success_desc = Action-Run war erfolgreich. settings.event_action_failure = Fehlschlag settings.event_action_success = Erfolg @@ -2941,14 +2941,14 @@ dashboard.cron.error=Fehler in Cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s ist beendet dashboard.delete_inactive_accounts=Alle nicht aktivierten Konten löschen dashboard.delete_inactive_accounts.started=Löschen aller nicht aktivierten Account-Aufgabe gestartet. -dashboard.delete_repo_archives=Lösche alle Repository-Archive (ZIP, TAR.GZ, etc.) +dashboard.delete_repo_archives=Lösche alle Repository-Archive (ZIP, TAR.GZ usw.) dashboard.delete_repo_archives.started=Löschen aller Repository-Archive gestartet. dashboard.delete_missing_repos=Alle Repository-Datensätze mit verloren gegangenen Git-Dateien löschen -dashboard.delete_missing_repos.started=Alle Repositorys löschen, die den Git-File-Task nicht gestartet haben. +dashboard.delete_missing_repos.started=Alle Repositorys löschen, die den Git-Dateien-Task nicht gestartet haben. dashboard.delete_generated_repository_avatars=Generierte Repository-Avatare löschen dashboard.sync_repo_branches=Fehlende Branches aus den Git-Daten in die Datenbank synchronisieren dashboard.update_mirrors=Spiegel aktualisieren -dashboard.repo_health_check=Healthchecks für alle Repositorys ausführen +dashboard.repo_health_check=Health-Prüfungen für alle Repositorys ausführen dashboard.check_repo_stats=Überprüfe alle Repository-Statistiken dashboard.archive_cleanup=Alte Repository-Archive löschen dashboard.deleted_branches_cleanup=Gelöschte Branches bereinigen @@ -2971,13 +2971,13 @@ dashboard.pointer_lookup_times=Anzahl Zeigerlookups dashboard.memory_allocate_times=Speicheranforderungen dashboard.memory_free_times=Speicherfreigaben dashboard.current_heap_usage=Aktuelle Heap-Auslastung -dashboard.heap_memory_obtained=Erhaltener Heap-Memory -dashboard.heap_memory_idle=Unbenutzter Heap-Memory -dashboard.heap_memory_in_use=Benutzter-Heap-Memory -dashboard.heap_memory_released=Freigegebener Heap-Memory +dashboard.heap_memory_obtained=Erhaltener Heap-Arbeitsspeicher +dashboard.heap_memory_idle=Unbenutzter Heap-Arbeitsspeicher +dashboard.heap_memory_in_use=Benutzter-Heap-Arbeitsspeicher +dashboard.heap_memory_released=Freigegebener Heap-Arbeitsspeicher dashboard.heap_objects=Heap-Objekte dashboard.bootstrap_stack_usage=Bootstrap-Stack-Auslastung -dashboard.stack_memory_obtained=Erhaltener Stack-Memory +dashboard.stack_memory_obtained=Erhaltener Stack-Arbeitsspeicher dashboard.mspan_structures_usage=MSpan-Structures-Auslastung dashboard.mspan_structures_obtained=Erhaltene MSpan-Structures dashboard.mcache_structures_usage=MCache-Structures-Auslastung @@ -3003,7 +3003,7 @@ dashboard.sync_branch.started=Synchronisierung der Branches gestartet dashboard.rebuild_issue_indexer=Issue-Indexer neu bauen users.user_manage_panel=Benutzerkonten verwalten -users.new_account=Benutzeraccount erstellen +users.new_account=Benutzerkonto erstellen users.name=Benutzername users.full_name=Vollständiger Name users.activated=Aktiviert @@ -3018,7 +3018,7 @@ users.created=Registriert am users.last_login=Letzte Anmeldung users.never_login=Hat sich noch nie eingeloggt users.send_register_notify=Benachrichtigung über Registrierung per E-Mail -users.new_success=Der Account „%s“ wurde erstellt. +users.new_success=Das Konto „%s“ wurde erstellt. users.edit=Bearbeiten users.auth_source=Authentifizierungsquelle users.local=Lokal @@ -3028,10 +3028,10 @@ users.update_profile_success=Das Benutzerkonto wurde aktualisiert. users.edit_account=Benutzerkonto bearbeiten users.max_repo_creation=Maximale Anzahl an Repositorys users.max_repo_creation_desc=(Gib -1 ein, um das globale Standardlimit zu verwenden.) -users.is_activated=Aktivierter Account -users.prohibit_login=Gesperrter Account -users.is_admin=Administrator-Account -users.is_restricted=Eingeschränkter Account +users.is_activated=Aktiviertes Konto +users.prohibit_login=Gesperrtes Konto +users.is_admin=Administrator-Konto +users.is_restricted=Eingeschränktes Konto users.allow_git_hook=Kann Git-Hooks erstellen users.allow_git_hook_tooltip=Git-Hooks werden mit denselben Benutzer-Rechten ausgeführt, mit denen Forgejo läuft, und haben die gleiche Ebene von Host-Zugriff. Dadurch können Benutzer mit diesen speziellen Git-Hook-Rechten auf alle Forgejo-Repositorys sowie auf die von Forgejo verwendete Datenbank zugreifen und diese ändern. Auch das Erhalten von Administratorrechten für Forgejo ist möglich. users.allow_import_local=Kann lokale Repositorys importieren @@ -3044,18 +3044,18 @@ users.still_has_org=Dieser Nutzer ist Mitglied einer Organisation. Du musst ihn users.purge=Benutzer löschen users.purge_help=Das Löschen des Benutzers inklusive all seiner Repositorys, Organisationen und Pakete erzwingen. Alle Kommentare und Issues, die von diesem Benutzer gepostet wurden, werden ebenso gelöscht. users.still_own_packages=Dieser Benutzer besitzt noch ein oder mehrere Pakete, lösche diese Pakete zuerst. -users.deletion_success=Der Account wurde gelöscht. +users.deletion_success=Das Konto wurde gelöscht. users.reset_2fa=2FA zurücksetzen users.list_status_filter.menu_text=Filter -users.list_status_filter.reset=Reset +users.list_status_filter.reset=Zurücksetzen users.list_status_filter.is_active=Aktiv users.list_status_filter.not_active=Inaktiv users.list_status_filter.is_admin=Administrator users.list_status_filter.not_admin=Nicht-Administrator users.list_status_filter.is_restricted=Eingeschränkt users.list_status_filter.not_restricted=Unbegrenzt -users.list_status_filter.is_prohibit_login=Login verbieten -users.list_status_filter.not_prohibit_login=Login erlaubt +users.list_status_filter.is_prohibit_login=Anmelden verbieten +users.list_status_filter.not_prohibit_login=Anmelden erlaubt users.list_status_filter.is_2fa_enabled=2FA aktiviert users.list_status_filter.not_2fa_enabled=2FA deaktiviert users.details=Benutzerdetails @@ -3102,12 +3102,12 @@ packages.size=Größe packages.published=Veröffentlicht defaulthooks=Standard-Webhooks -defaulthooks.desc=Webhooks senden automatisch HTTP-POST-Anfragen an einen Server, wenn bestimmte Forgejo-Events ausgelöst werden. Hier definierte Webhooks sind die Standardwerte, die in alle neuen Repositorys kopiert werden. Mehr Infos findest du in der Webhooks-Anleitung (auf Englisch). +defaulthooks.desc=Webhooks senden automatisch HTTP-POST-Anfragen an einen Server, wenn bestimmte Forgejo-Ereignisse ausgelöst werden. Hier definierte Webhooks sind die Standardwerte, die in alle neuen Repositorys kopiert werden. Mehr Infos findest du in der Webhooks-Anleitung (auf Englisch). defaulthooks.add_webhook=Standard-Webhook hinzufügen defaulthooks.update_webhook=Standard-Webhook aktualisieren systemhooks=System-Webhooks -systemhooks.desc=Webhooks senden automatisch HTTP-POST-Anfragen an einen Server, wenn bestimmte Forgejo-Events ausgelöst werden. Hier definierte Webhooks werden auf alle Repositorys des Systems übertragen, beachte daher mögliche Performance-Einbrüche. Mehr Infos findest du in der Webhooks-Anleitung (auf Englisch). +systemhooks.desc=Webhooks senden automatisch HTTP-POST-Anfragen an einen Server, wenn bestimmte Forgejo-Ereignisse ausgelöst werden. Hier definierte Webhooks werden auf alle Repositorys des Systems übertragen, beachte daher mögliche Performance-Einbrüche. Mehr Infos findest du in der Webhooks-Anleitung (auf Englisch). systemhooks.add_webhook=System-Webhook hinzufügen systemhooks.update_webhook=System-Webhook aktualisieren @@ -3142,9 +3142,9 @@ auths.search_page_size=Seitengröße auths.filter=Benutzerfilter auths.admin_filter=Admin-Filter auths.restricted_filter=Eingeschränkte Filter -auths.restricted_filter_helper=Leer lassen, um keine Benutzer als eingeschränkt festzulegen. Verwende einen Asterisk („*“), um alle Benutzer, die nicht dem Admin-Filter entsprechen, als eingeschränkt zu setzen. +auths.restricted_filter_helper=Leer lassen, um keine Benutzer als eingeschränkt festzulegen. Verwende ein Sternchen („*“), um alle Benutzer, die nicht dem Admin-Filter entsprechen, als eingeschränkt zu setzen. auths.verify_group_membership=Gruppenmitgliedschaft in LDAP verifizieren (zum Überspringen leer lassen) -auths.group_search_base=Gruppensuche Basisdomainname +auths.group_search_base=Gruppensuche-Basisdomainname auths.group_attribute_list_users=Gruppenattribut, welches Benutzerliste enthält auths.user_attribute_in_group=Benutzerattribut in der Gruppenliste auths.map_group_to_team=Ordne LDAP-Gruppen Organisationsteams zu (zum Überspringen leer lassen) @@ -3175,7 +3175,7 @@ auths.oauth2_authURL=Authorisierungs-URL auths.oauth2_profileURL=Profil-URL auths.oauth2_emailURL=E-Mail-URL auths.skip_local_two_fa=Lokale 2FA überspringen -auths.skip_local_two_fa_helper=Das Leerlassen bedeutet, dass lokale User die 2FA immer noch bestehen müssen, um sich anzumelden +auths.skip_local_two_fa_helper=Leerlassen bedeutet, dass lokale Benutzer die 2FA weiterhin durchführen müssen, um sich anzumelden auths.oauth2_tenant=Inhaber auths.oauth2_scopes=Zusätzliche Bereiche auths.oauth2_required_claim_name=Benötigter Claim-Name @@ -3184,15 +3184,15 @@ auths.oauth2_required_claim_value=Benötigter Claim-Wert auths.oauth2_required_claim_value_helper=Setze diesen Wert, damit Nutzer aus dieser Quelle sich nur anmelden dürfen, wenn sie einen Claim mit diesem Namen und Wert besitzen auths.oauth2_group_claim_name=Claim-Name, der Gruppennamen für diese Quelle angibt (optional). auths.oauth2_admin_group=Gruppen-Claim-Wert für Administratoren (optional – erfordert Claim-Namen oben). -auths.oauth2_restricted_group=Gruppen-Claim-Wert für eingeschränkte User. (Optional – erfordert Claim-Namen oben) -auths.oauth2_map_group_to_team=Gruppen aus OAuth-Claims den Organisationsteams zuordnen (optional – oben muss der Name des Claims angegeben werden). +auths.oauth2_restricted_group=Gruppen-Claim-Wert für eingeschränkte Benutzer (optional – erfordert Claim-Namen oben). +auths.oauth2_map_group_to_team=Gruppen aus OAuth-Claims den Organisationsteams zuordnen (optional – erfordert Claim-Namen oben). auths.oauth2_map_group_to_team_removal=Benutzer aus synchronisierten Teams entfernen, wenn der Benutzer nicht zur entsprechenden Gruppe gehört. auths.tips=Tipps auths.tips.oauth2.general=OAuth2-Authentifizierung auths.tips.oauth2.general.tip=Beim Registrieren einer OAuth2-Anwendung sollte die Callback-URL folgendermaßen lauten: auths.tip.oauth2_provider=OAuth2-Anbieter auths.tip.bitbucket=Registriere einen neuen OAuth-Consumer unter %s -auths.tip.nextcloud=Registriere einen neuen OAuth-Consumer auf deiner Instanz über das folgende Menü: „Settings -> Security -> OAuth 2.0 client“ +auths.tip.nextcloud=Registriere einen neuen OAuth-Consumer auf deiner Instanz über das folgende Menü: „Einstellungen -> Sicherheit -> OAuth-2.0-Client“ auths.tip.dropbox=Erstelle eine neue App auf %s auths.tip.facebook=Erstelle eine neue Anwendung auf %s und füge das Produkt „Facebook Login“ hinzu auths.tip.github=Registriere unter %s eine neue OAuth-Anwendung @@ -3202,20 +3202,20 @@ auths.tip.twitter=Gehe auf %s, erstelle eine Anwendung und stelle sicher, dass d auths.tip.discord=Registriere unter %s eine neue Anwendung auths.tip.gitea=Registriere eine neue OAuth2-Anwendung. Eine Anleitung findest du unter %s auths.tip.yandex=`Erstelle eine neue Anwendung auf %s. Wähle folgende Berechtigungen aus dem Abschnitt „Yandex.Passport API“: „Zugriff auf E-Mail-Adresse“, „Zugriff auf Benutzeravatar“ und „Zugriff auf Benutzername, Vor- und Nachname, Geschlecht“` -auths.tip.mastodon=Gib eine benutzerdefinierte URL für die Mastodon-Instanz ein, mit der du dich authentifizieren möchtest (oder benutze die standardmäßige) -auths.edit=Authentifikationsquelle bearbeiten -auths.activated=Diese Authentifikationsquelle ist aktiviert +auths.tip.mastodon=Gib eine benutzerdefinierte URL für die Mastodon-Instanz ein, mit der du dich authentifizieren möchtest (oder verwende die Standard-URL) +auths.edit=Authentifizierungsquelle bearbeiten +auths.activated=Diese Authentifizierungsquelle ist aktiviert auths.new_success=Die Authentifizierung „%s“ wurde hinzugefügt. auths.update_success=Diese Authentifizierungsquelle wurde aktualisiert. auths.update=Authentifizierungsquelle aktualisieren -auths.delete=Authentifikationsquelle löschen +auths.delete=Authentifizierungsquelle löschen auths.delete_auth_title=Authentifizierungsquelle löschen auths.delete_auth_desc=Das Löschen einer Authentifizierungsquelle verhindert, dass Benutzer sich darüber anmelden können. Fortfahren? auths.still_in_used=Diese Authentifizierungsquelle wird noch verwendet. Bearbeite oder lösche zuerst alle Benutzer, die diese Authentifizierungsquelle benutzen. auths.deletion_success=Die Authentifizierungsquelle „%s“ wurde gelöscht. auths.login_source_exist=Die Authentifizierungsquelle „%s“ existiert bereits. auths.login_source_of_type_exist=Eine Authentifizierungart dieses Typs existiert bereits. -auths.unable_to_initialize_openid=Provider für OpenID Connect konnte nicht initialisiert werden: %s +auths.unable_to_initialize_openid=OpenID-Connect-Anbieter konnte nicht initialisiert werden: %s auths.invalid_openIdConnectAutoDiscoveryURL=Ungültige Auto-Discovery-URL (dies muss eine gültige URL sein, die mit http:// oder https:// beginnt) config.server_config=Serverkonfiguration @@ -3228,7 +3228,7 @@ config.domain=Server-Domain config.offline_mode=Lokaler Modus config.disable_router_log=Router-Log deaktivieren config.run_user=Ausführen als -config.run_mode=Laufzeit-Modus +config.run_mode=Betriebsmodus config.git_version=Git-Version config.app_data_path=App-Datenpfad config.repo_root_path=Repository-Wurzelpfad @@ -3264,7 +3264,7 @@ config.db_ssl_mode=SSL config.db_path=Verzeichnis config.service_config=Service-Konfiguration -config.register_email_confirm=E-Mail-Bestätigung benötigt zum Registrieren +config.register_email_confirm=E-Mail-Bestätigung zur Registrierung erforderlich config.disable_register=Selbstregistrierung deaktivieren config.allow_only_internal_registration=Registrierung nur über Forgejo selbst erlauben config.allow_only_external_registration=Registrierung nur über externe Dienste erlauben @@ -3321,14 +3321,14 @@ config.cache_item_ttl=Cache-Item-TTL config.session_config=Session-Konfiguration config.session_provider=Session-Anbieter -config.provider_config=Provider-Einstellungen +config.provider_config=Anbieter-Einstellungen config.cookie_name=Cookie-Name config.gc_interval_time=GC-Intervall config.session_life_time=Session-Lebensdauer config.https_only=Nur HTTPS config.cookie_life_time=Cookie-Lebensdauer -config.picture_config=Bild-und-Profilbild-Konfiguration +config.picture_config=Bild- und Avatar-Konfiguration config.picture_service=Bilderdienst config.disable_gravatar=Gravatar deaktivieren config.enable_federated_avatar=Föderierte Profilbilder einschalten @@ -3383,7 +3383,7 @@ monitor.queue.exemplar=Beispieltyp monitor.queue.numberworkers=Anzahl der Worker monitor.queue.activeworkers=Aktive Worker monitor.queue.maxnumberworkers=Maximale Anzahl der Worker -monitor.queue.numberinqueue=Nummer in der Warteschlange +monitor.queue.numberinqueue=Anzahl in der Warteschlange monitor.queue.review_add=Worker hinzufügen/prüfen monitor.queue.settings.title=Pool-Einstellungen monitor.queue.settings.desc=Pools wachsen dynamisch basierend auf der Blockierung der Arbeitswarteschlange. @@ -3411,7 +3411,7 @@ notices.op=Aktion notices.delete_success=Diese Systemmeldung wurde gelöscht. self_check.database_fix_mysql = Für MySQL-/MariaDB-Benutzer: Du kannst den Befehl „forgejo doctor convert“ verwenden, um die Collation-Probleme zu lösen, oder du kannst das Problem mit „ALTER … COLLATE …“-SQLs manuell lösen. dashboard.sync_tag.started = Tag-Synchronisierung gestartet -self_check.database_collation_case_insensitive = Datenbank benutzt eine Collation %s, welcher der Groß-/Kleinschreibung egal ist. Obwohl Forgejo damit arbeiten könnte, könnte es ein paar seltene Fälle geben, bei denen es nicht wie erwartet funktioniert. +self_check.database_collation_case_insensitive = Die Datenbank verwendet die Collation %s, die nicht zwischen Groß- und Kleinschreibung unterscheidet. Forgejo kann damit arbeiten, es gibt aber seltene Fälle, in denen es nicht wie erwartet funktioniert. self_check = Selbstprüfung dashboard.sync_repo_tags = Tags aus Git-Daten zu Datenbank synchronisieren emails.change_email_text = Bist du dir sicher, dass du diese E-Mail-Addresse aktualisieren möchtest? @@ -3427,14 +3427,14 @@ auths.tip.gitlab_new = Registriere eine neue Anwendung auf %s auths.default_domain_name = Standarddomainname, der für die E-Mail-Adresse benutzt wird config.app_slogan = Instanz-Slogan config.cache_test_failed = Konnte den Cache nicht untersuchen: %v. -config.cache_test_succeeded = Cache-Test erfolgreich, eine Antwort erhalten in %s. +config.cache_test_succeeded = Cache-Test erfolgreich, Antwort in %s erhalten. config.cache_test = Cache testen config.cache_test_slow = Cache-Test erfolgreich, aber die Antwort ist langsam: %s. users.block.description = Diesem Benutzer verbieten, durch sein Konto mit diesem Dienst zu interagieren, und ihn am Einloggen hindern. users.restricted.description = Nur Interaktionen mit den Repositorys und Organisationen erlauben, wo der Benutzer als Mitarbeiter hinzugefügt wurde. Dies verhindert Zugriff auf öffentliche Repositorys in dieser Instanz. users.local_import.description = Import von Repositorys aus dem lokalen Dateisystem des Servers erlauben. Dies kann ein Sicherheitsproblem sein. users.organization_creation.description = Erstellung neuer Organisationen erlauben. -users.activated.description = Abschluss der E-Mail-Verifizierung. Der Besitzer eines nicht aktivierten Accounts wird nicht in der Lage sein, sich einzuloggen, bis die E-Mail-Verifikation abgeschlossen wurde. +users.activated.description = Abschluss der E-Mail-Verifizierung. Der Besitzer eines nicht aktivierten Kontos wird nicht in der Lage sein, sich anzumelden, bis die E-Mail-Verifikation abgeschlossen wurde. users.admin.description = Diesem Benutzer vollständigen Zugriff zu allen administrativen Funktionen gewähren, die über das Web-UI und die API verfügbar sind. emails.delete = E-Mail-Adresse löschen emails.deletion_success = Die E-Mail-Adresse wurde gelöscht. @@ -3468,7 +3468,7 @@ mirror_sync_push=Commits zu %[3]s bei %[4]s< mirror_sync_create=neue Referenz %[3]s bei %[4]s wurde von einem Spiegel synchronisiert mirror_sync_delete=hat die Referenz des Spiegels %[2]s in %[3]s synchronisiert und gelöscht approve_pull_request=`hat %[3]s#%[2]s genehmigt` -reject_pull_request=`schlug Änderungen für %[3]s#%[2]s vor` +reject_pull_request=`schlug Änderungen an %[3]s#%[2]s vor` publish_release=`veröffentlichte Release %[4]s in %[3]s` review_dismissed=`verwarf die Sichtung von %[4]s in %[3]s#%[2]s` review_dismissed_reason=Grund: @@ -3696,7 +3696,7 @@ arch.version.provides = Bietet arch.version.groups = Gruppe arch.version.depends = Hängt ab von arch.version.makedepends = Make-Abhängigkeit -arch.version.checkdepends = Check-Abhängigkeit +arch.version.checkdepends = Prüfungs-Abhängigkeit arch.version.conflicts = Konflikte arch.version.replaces = Ersetzt arch.version.backup = Backup @@ -3827,7 +3827,7 @@ workflow.dispatch.trigger_found = Dieser Workflow hat einen workflow_dispatch workflow.dispatch.success = Ausführung des Workflows wurde erfolgreich angefragt. runs.expire_log_message = Logs wurden gelöscht, weil sie zu alt waren. runs.no_workflows.help_write_access = Keine Ahnung, wie man mit Forgejo Actions anfangen soll? Schau im Schnellstart in der Benutzerdokumentation vorbei, um deinen ersten Workflow zu schreiben, dann setze einen Forgejo-Runner auf, um deine Jobs auszuführen. -runs.no_workflows.help_no_write_access = Um über Forgejo Actions zu lernen, siehe die Dokumentation. +runs.no_workflows.help_no_write_access = Um mehr über Forgejo Actions zu erfahren, siehe die Dokumentation. variables.not_found = Die Variable wurde nicht gefunden. [projects] @@ -3841,7 +3841,7 @@ changed_filemode=%[1]s → %[2]s directory=Verzeichnis normal_file=Normale Datei executable_file=Ausführbare Datei -symbolic_link=Softlink +symbolic_link=Symbolischer Link submodule=Submodul @@ -3862,14 +3862,14 @@ branch_kind = Branches suchen … commit_kind = Commits suchen … runner_kind = Runner suchen … no_results = Keine passenden Ergebnisse gefunden. -code_search_unavailable = Die Code-Suche ist momentan nicht verfügbar. Bitte kontaktiere den Webseitenadministrator. +code_search_unavailable = Die Code-Suche ist momentan nicht verfügbar. Bitte kontaktiere den Instanz-Administrator. keyword_search_unavailable = Die Suche mittels Schlüsselwort ist momentan nicht verfügbar. Bitte kontaktiere den Webseitenadministrator. exact = Exakt exact_tooltip = Nur Ergebnisse einbinden, die auf den exakten Suchbegriff passen issue_kind = Issues suchen … pull_kind = Pulls suchen … union = Vereinigungsmenge -union_tooltip = Ergebnisse, die auf ein beliebiges von den Whitespace getrennten Schlüsselwörtern passen, einbinden +union_tooltip = Ergebnisse einbeziehen, die auf ein beliebiges der durch Leerzeichen getrennten Schlüsselwörter passen regexp = RegExp regexp_tooltip = Suchbegriff als regulären Ausdruck interpretieren @@ -3903,7 +3903,7 @@ wiki.read = Lesen: Das integrierte Wiki und seine Historie lesen. wiki.write = Schreiben: Seiten im integrierten Wiki erstellen, aktualisieren und löschen. projects.read = Lesen: Zugriff auf Projektboards des Repositorys. projects.write = Schreiben: Projekte und Spalten erstellen und bearbeiten. -packages.read = Lesen: Pakete dieses Repositorys betrachten und herunterladen. +packages.read = Lesen: Pakete dieses Repositorys einsehen und herunterladen. packages.write = Schreiben: Pakete dieses Repositorys veröffentlichen und löschen. actions.read = Lesen: Workflow-Ausführungen und ihre Logs betrachten. actions.write = Schreiben: Workflows auslösen, neu starten und abbrechen. Vertrauensdelegation an Pull-Request-Einreicher verwalten. diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index 065dc85b98..6e11db0cbf 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -650,10 +650,10 @@ watched=Ακολουθούμενα αποθετήρια code=Κώδικας projects=Έργα overview=Επισκόπηση -following_few=%d ακολουθεί +following_few=ακολουθεί %d follow=Ακολούθηση -unfollow=Να μην ακολουθώ -user_bio=Περιγραφή +unfollow=Άρση ακολούθησης +user_bio=Βιογραφικό disabled_public_activity=Αυτός ο χρήστης έχει απενεργοποιήσει τη δημόσια προβολή της δραστηριότητας του. email_visibility.limited=Η διεύθυνση email σας είναι ορατή σε κάθε ταυτοποιημένο χρήστη show_on_map=Προβολή σε χάρτη @@ -897,7 +897,7 @@ create_oauth2_application_button=Δημιουργία εφαρμογής create_oauth2_application_success=Δημιουργήσατε επιτυχώς μια νέα εφαρμογή OAuth2. update_oauth2_application_success=Ενημερώσατε την εφαρμογή OAuth2 επιτυχώς. oauth2_application_name=Όνομα εφαρμογής -oauth2_confidential_client=Εμπιστευτικός πελάτης (client). Επιλέξτε το για εφαρμογές που διατηρούν το μυστικό κωδικό κρυφό, όπως π.χ. εφαρμογές ιστού. Μην επιλέγετε για εγγενείς εφαρμογές, συμπεριλαμβανομένων εφαρμογών επιφάνειας εργασίας και εφαρμογών για κινητά. +oauth2_confidential_client=Εμπιστευτικός πελάτης (client). Επιλέξτε το για εφαρμογές που διατηρούν το μυστικό κωδικό κρυφό, όπως π.χ. εφαρμογές ιστού. Μην επιλέγετε για εγγενείς εφαρμογές, συμπεριλαμβανομένων εφαρμογών για υπολογιστές και για κινητά. oauth2_redirect_uris=URI Ανακατεύθυνσης. Χρησιμοποιήστε μια νέα γραμμή για κάθε URI. save_application=Αποθήκευση oauth2_client_id=Ταυτότητα Πελάτη @@ -2401,7 +2401,7 @@ settings.archive.tagsettings_unavailable=Οι ρυθμίσεις ετικέτα settings.unarchive.button=Αναίρεση αρχειοθέτησης αποθετηρίου settings.unarchive.header=Απο-Αρχειοθέτηση του αποθετηρίου settings.unarchive.text=Η απο-αρχειοθέτηση του αποθετηρίου θα αποκαταστήσει την ικανότητά του να λαμβάνει υποβολές και ωθήσεις, καθώς και νέα ζητήματα και pull-requests. -settings.unarchive.success=Το repository απο-αρχειοθετήθηκε με επιτυχία. +settings.unarchive.success=Το αποθετήριο απο-αρχειοθετήθηκε με επιτυχία. settings.unarchive.error=Παρουσιάστηκε σφάλμα κατά την προσπάθεια απο-αρχειοθέτησης του αποθετηρίου. Δείτε τις καταγραφές για περισσότερες λεπτομέρειες. settings.update_avatar_success=Η εικόνα του αποθετηρίου έχει ενημερωθεί. settings.lfs=LFS @@ -2673,7 +2673,7 @@ issues.author.tooltip.pr = Αυτό το pull request δημιουργήθηκε settings.federation_settings = Ρυθμίσεις διαλειτουργικότητας settings.federation_apapiurl = Το Federation URL (διαλειτουργικότητας) του αποθετηρίου. Αντιγράψτε το στις ρυθμίσεις διαλειτουργικότητας ενός άλλου αποθετηρίου ως το URL ενός Ακολουθούμενου Αποθετηρίου. form.string_too_long = Το κείμενο είναι μεγαλύτερο από %d χαρακτήρες. -release.hide_archive_links = Απόκρυψη αυτόματα δημιουργημένων archive +release.hide_archive_links = Απόκρυψη αυτόματα δημιουργημένων αρχείων λήψης settings.graphql_url = URL του GraphQL issues.edit.already_changed = Δεν ήταν δυνατή η αποθήκευση των αλλαγών στο ζήτημα αυτό, επειδή το περιεχόμενο έχει ήδη αλλαχθεί από κάποιον άλλο χρήστη. Για να μην χαθούν οι αλλαγές του, ανανεώστε την σελίδα και προσπαθήστε να το επεξεργαστείτε ξανά project = Έργα @@ -2895,7 +2895,7 @@ teams.invite.title=Έχετε προσκληθεί να συμμετάσχετε teams.invite.by=Προσκλήθηκε από %s teams.invite.description=Παρακαλώ κάντε κλικ στον παρακάτω σύνδεσμο για συμμετοχή στην ομάδα. follow_blocked_user = Δεν μπορείτε να ακολουθήσετε τον οργανισμό, επειδή σας έχει αποκλείσει. -open_dashboard = Δημιουργία πίνακα δραστηριότητας +open_dashboard = Άνοιγμα πίνακα ελέγχου settings.change_orgname_redirect_prompt.with_cooldown.one = Το παλιό όνομα οργανισμού θα είναι διαθέσιμο σε όλους μετά από καθυστέρηση %[1]d ημέρας. Μπορείτε ακόμα να ανακτήσετε το παλιό όνομα κατά τη διάρκεια αυτής. settings.change_orgname_redirect_prompt.with_cooldown.few = Το παλιό όνομα οργανισμού θα είναι διαθέσιμο σε όλους μετά από καθυστέρηση %[1]d ημερών. Μπορείτε ακόμα να ανακτήσετε το παλιό όνομα κατά τη διάρκεια αυτής. @@ -2955,7 +2955,7 @@ dashboard.update_migration_poster_id=Ενημέρωση των ID συντακτ dashboard.git_gc_repos=Garbage collect όλων των αποθετηρίων dashboard.resync_all_sshkeys=Ενημέρωση του αρχείου «.ssh/authorized_keys» με τα κλειδιά SSH του Forgejo. dashboard.resync_all_sshprincipals=Ενημέρωση του αρχείου «.ssh/authorized_principals» με τις αρχές SSH του Forgejo. -dashboard.resync_all_hooks=Επανασυγχρονισμός των hook pre-receive, update και post-receive όλων των αποθετηρίων +dashboard.resync_all_hooks=Επανασυγχρονισμός των Git hook όλων των αποθετηρίων (pre-receive, update, post-receive, proc-receive, …) dashboard.reinit_missing_repos=Επανεκκινήστε όλα τα αποθετήρια Git που λείπουν και για τα οποία υπάρχουν εγγραφές dashboard.sync_external_users=Συγχρονισμός δεδομένων εξωτερικών χρηστών dashboard.cleanup_hook_task_table=Εκκαθάριση πίνακα hook_task diff --git a/options/locale/locale_eo.ini b/options/locale/locale_eo.ini index fd69e375aa..16cb2d2de4 100644 --- a/options/locale/locale_eo.ini +++ b/options/locale/locale_eo.ini @@ -499,6 +499,8 @@ repo.transfer.subject_to_you = %s volas reposedigi la deponejon "%s" al vi totp_enrolled.subject = Vi aktivigis TOTP-n kiel 2FA metodo issue_assigned.issue = @%[1]s asignis al vi ĉi tiun eraron %[2]s en la deponejo %[3]s. +repo.transfer.subject_to = %s volas transigi deponejon "%s" al %s + [form] TeamName = Gruponomo RepoName = Deponejonomo @@ -576,6 +578,11 @@ To = Branĉonomo AccessToken = Atingoĵetono required_prefix = La enigaĵo devas komenciĝi per "%s" +username_error = ` enhavu sole literojn («a–z», «A–Z»), numerojn («0–9«), strekojn («-»), substrekojn («_») kaj punktojn («.»). Gi ne povas komenci kun ne-alfanumeraj signoj, kaj sinsekva ne-alfanumeraj signoj ankaŭ estas malpermesitaj.` + +PayloadUrl = Utilaĵ-URL +CommitChoice = Enmeto elekton + [modal] confirm = Konfirmi no = Ne @@ -710,7 +717,7 @@ password_incorrect = La nuna pasvorto malĝustas. gpg_helper = Ĉu bezonas helpon? Legetu la gvidon pri GPG. choose_new_avatar = Elekti novan profilbildon activated = Konfirmita -add_new_email = Aldoni novan retpoŝtadreson +add_new_email = Aldoni retpoŝtadreson verify_gpg_key_success = GPG-ŝlosilo «%s» jam konfirmiĝis. show_openid = Montri je profilo hide_openid = Kaŝi de profilo @@ -738,7 +745,7 @@ ssh_key_deletion_desc = Forigi SSH-ŝlosilon reprenus ĝian aliron al via konto. permission_no_access = Neniu aliro comment_type_group_dependency = Dependaĵo change_password_success = Via pasvorto konserviĝis. Salutu ekde nun per tiu nova pasvorto. -email_deletion_desc = La retpoŝtmesaĝo kaj rilataj informoj forviŝiĝos de via konto. Git-enmetoj de tiu ĉi adreso restos senŝanĝaj. Ĉu daŭrigu? +email_deletion_desc = Tiu ĉi retpoŝtadreso kaj rilataj informoj forviŝiĝos de via konto. Git-enmetoj de tiu ĉi adreso restos senŝanĝaj. Ĉu daŭrigu? permissions_list = Permesoj: permission_write = Lega kaj Skriba key_content = Enhavo @@ -768,7 +775,7 @@ enable_custom_avatar = Uzi propran profilbildon change_password = Ŝanĝi pasvorton keep_pronouns_private = Montri pronomojn nur al la aŭtentikigitaj uzantoj keep_pronouns_private.description = Tio maskos viajn pronomojn kontraŭ neaŭtentikigitaj vizitantoj. -add_new_principal = +add_new_principal = gpg_token_required = Vi devas disponigi signaturon por la malsupran ĵetono gpg_token = Ĵetono gpg_token_help = Vi povas generi signaturon uzante: @@ -919,6 +926,15 @@ migrate_items_releases = Eldonoj commits.commits = Enmetoj rss.must_be_on_branch = Vi devas esti en branĉo por havi RSS-fluon. +repo_name = Deponejonomo +size_format = %[1]s: %[2]s; %[3]s: %[4]s +template = Ŝablono +template_select = Elektu ŝablonon + +editor.name_your_file = Nomu vian dosieron… +editor.or = aŭ +editor.add_tmpl.filename = dosiernomo + [org] code = Fontkodo settings = Agordoj @@ -976,4 +992,7 @@ directory = Dosierujo normal_file = Normala dosiero executable_file = Rulebla dosiero symbolic_link = Simbola ligilo -submodule = Submodulo \ No newline at end of file +submodule = Submodulo + +[translation_meta] +test = Mi prononcas Forgejo per g-sono. Ĝi ja ne estas literumita forĝejo :) \ No newline at end of file diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 224864c24a..bb77f40d99 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -32,7 +32,7 @@ password=Contraseña access_token=Token de acceso re_type=Confirmar contraseña captcha=CAPTCHA -twofa=Autenticación de dos factores +twofa=Autenticación de doble factor twofa_scratch=Código de respaldo passcode=Código de acceso @@ -80,9 +80,9 @@ rerun_all=Volver a ejecutar todos los trabajos save=Guardar add=Añadir add_all=Añadir todos -remove=Eliminar -remove_all=Eliminar todos -remove_label_str=`Eliminar elemento "%s"` +remove=Retirar +remove_all=Retirar todos +remove_label_str=`Retirar elemento "%s"` edit=Editar enabled=Activo @@ -103,7 +103,7 @@ preview=Vista previa loading=Cargando… error=Error -error404=La página a la que está intentando acceder no existe,ha sido eliminada o no está autorizado a verla. +error404=La página a la que está intentando acceder no existe,ha sido retirada o no está autorizado a verla. go_back=Volver never=Nunca @@ -147,7 +147,7 @@ filter.private = Privado toggle_menu = Alternar menú invalid_data = Datos inválidos: %v confirm_delete_artifact = ¿Estás seguro de que deseas eliminar el artefacto "%s"? -more_items = Mas cosas +more_items = Mas elementos copy_generic = Copiar al portapapeles filter.not_fork = No hay bifurcaciones filter.is_fork = Bifurcaciones @@ -178,8 +178,8 @@ contributions_format = {contributions} el {day} {month} {year} [editor] buttons.heading.tooltip=Añadir encabezado -buttons.bold.tooltip=Añadir texto en negrita -buttons.italic.tooltip=Añadir texto en cursiva +buttons.bold.tooltip=Añadir texto en negrita (Ctrl+B / ⌘B) +buttons.italic.tooltip=Añadir texto en cursiva (Ctrl+I / ⌘I) buttons.quote.tooltip=Citar texto buttons.code.tooltip=Añadir código buttons.link.tooltip=Añadir un enlace @@ -202,7 +202,7 @@ table_modal.placeholder.content = Contenido link_modal.header = Añadir enlace link_modal.description = Descripción link_modal.paste_reminder = Pista: Con una URL en tu portapapeles, puedes pegar directamente en el editor para crear un enlace. -link_modal.url = URL +link_modal.url = Url [filter] string.asc=A - Z @@ -384,8 +384,8 @@ manual_activation_only=Póngase en contacto con el administrador del sitio para remember_me=Recordar este dispositivo forgot_password_title=Contraseña olvidada forgot_password=¿Has olvidado tu contraseña? -sign_up_successful=La cuenta se ha creado correctamente. ¡Le damos la bienvenida! -confirmation_mail_sent_prompt=Se ha enviado un nuevo correo de confirmación a %s. Para completar el proceso de registro, revisa tu bandeja de entrada y sigue el enlace proporcionado dentro de los próximos %s. Si la dirección no es correcto, puedes iniciar sesión y solicitar otro correo de confirmación para ser enviado a una dirección diferente. +sign_up_successful=La cuenta se ha creado correctamente. ¡Bienvenido! +confirmation_mail_sent_prompt=Se ha enviado un nuevo correo electrónico de confirmación a %s. Para completar el registro, comprueba tu bandeja de entrada y sigue el enlace que aparece en el correo en un plazo de: %s. Si la dirección de correo electrónico no es correcta, puedes iniciar sesión y solicitar que se envíe otro correo electrónico de confirmación a otra dirección. must_change_password=Actualizar su contraseña allow_password_change=Obligar al usuario a cambiar la contraseña (recomendado) reset_password_mail_sent_prompt=Se ha enviado un correo de confirmación a %s. Para completar el proceso de recuperación de la cuenta, consulta tu bandeja de entrada y sigue el enlace proporcionado dentro de los próximos %s. @@ -442,7 +442,7 @@ password_pwned_err=No se pudo completar la solicitud a HaveIBeenPwned change_unconfirmed_email = Si has proporcionado una dirección de correo electrónico errónea durante el registro, la puedes cambiar debajo y se enviará una confirmación a la nueva dirección. change_unconfirmed_email_error = No es posible cambiar la dirección de correo electrónico: %v change_unconfirmed_email_summary = Cambia la dirección de correo electrónico a quien se envía el correo de activación. -last_admin = No puedes eliminar al último admin (administrador). Debe haber, al menos, un admin. +last_admin = No puedes retirar el último admin (administrador). Debe haber, al menos, un admin. sign_up_button = Regístrate ahora. hint_login = ¿Ya tienes cuenta? ¡Ingresa ahora! hint_register = ¿Necesitas una cuenta? Regístrate ahora. @@ -516,7 +516,7 @@ admin.new_user.subject = Se acaba de registrar el nuevo usuario %s admin.new_user.user_info = Información del usuario admin.new_user.text = Por favor, pulsa aquí para gestionar este usuario desde el panel de administración. account_security_caution.text_1 = Si fuiste tú, puedes ignorar este correo. -removed_security_key.subject = Se ha eliminado una clave de seguridad +removed_security_key.subject = Se ha retirado una clave de seguridad removed_security_key.no_2fa = Ya no hay otros métodos 2FA configurados, lo que significa que ya no es necesario iniciar sesión en tu cuenta con 2FA. password_change.subject = Tu contraseña ha sido modificada password_change.text_1 = La contraseña de tu cuenta acaba de ser modificada. @@ -527,7 +527,7 @@ totp_disabled.no_2fa = Ya no hay otros métodos 2FA configurados, lo que signifi account_security_caution.text_2 = Si no fuiste tú, tu cuenta está comprometida. Ponte en contacto con los administradores de este sitio. totp_enrolled.subject = Has activado TOTP como método 2FA totp_enrolled.text_1.no_webauthn = Acabas de activar TOTP para tu cuenta. Esto significa que para todos los futuros inicios de sesión en tu cuenta, debes utilizar TOTP como método 2FA. -removed_security_key.text_1 = La clave de seguridad "%[1]s" acaba de ser eliminada de tu cuenta. +removed_security_key.text_1 = La clave de seguridad "%[1]s" acaba de ser retirada de tu cuenta. primary_mail_change.text_1 = El correo principal de su cuenta acaba de cambiar a %[1]s. Esto significa que esta dirección de correo electrónico ya no recibirá notificaciones por correo electrónico de su cuenta. totp_enrolled.text_1.has_webauthn = Acabas de activar TOTP para tu cuenta. Esto significa que para todos los futuros inicios de sesión en tu cuenta, podrás utilizar TOTP como método 2FA o bien utilizar cualquiera de tus claves de seguridad. @@ -603,7 +603,7 @@ enterred_invalid_owner_name=El nuevo nombre de usuario no es válido. enterred_invalid_password=La contraseña que ha introducido es incorrecta. user_not_exist=Este usuario no existe. team_not_exist=Este equipo no existe. -last_org_owner=No puedes eliminar al último usuario del equipo de "propietarios". Todas las organizaciones deben tener al menos un propietario. +last_org_owner=No puedes retirar el último usuario del equipo de "propietarios". Todas las organizaciones deben tener al menos un propietario. cannot_add_org_to_team=Una organización no puede ser añadida como miembro de un equipo. duplicate_invite_to_team=El usuario ya fue invitado como miembro del equipo. organization_leave_success=Ha abandonado correctamente la organización %s. @@ -622,7 +622,7 @@ org_still_own_repo=Esta organización todavía posee uno o más repositorios, el org_still_own_packages=Esta organización todavía posee uno o más paquetes, elimínalos primero. target_branch_not_exist=La rama de destino no existe. -admin_cannot_delete_self = No puedes eliminarte a ti mismo cuando eres un admin (administrador). Por favor, elimina primero tus privilegios de administrador. +admin_cannot_delete_self = No puedes eliminarte a ti mismo cuando eres un admin (administrador). Por favor, primero retire los privilegios de administrador. username_error_no_dots = ` solo puede contener carácteres alfanuméricos ("0-9","a-z","A-Z"), guiones ("-"), y guiones bajos ("_"). No puede empezar o terminar con carácteres no alfanuméricos y también están prohibidos los carácteres no alfanuméricos consecutivos.` unsupported_login_type = No se admite el tipo de inicio de sesión para eliminar la cuenta. required_prefix = La entrada debe empezar por "%s" @@ -738,7 +738,7 @@ comment_type_group_review_request=Revisión solicitada comment_type_group_pull_request_push=Confirmaciones añadidas comment_type_group_project=Proyecto comment_type_group_issue_ref=Referencia del incidente -saved_successfully=Su configuración se ha guardado correctamente. +saved_successfully=Tu configuración se guardó correctamente. privacy=Privacidad keep_activity_private=Ocultar actividad de la página de perfil lookup_avatar_by_mail=Buscar avatar por dirección de correo electrónico @@ -772,8 +772,8 @@ activate_email=Enviar activación activations_pending=Activaciones pendientes can_not_add_email_activations_pending=Hay una activación pendiente, inténtelo de nuevo en unos minutos si desea agregar un nuevo correo electrónico. delete_email=Eliminar -email_deletion=Eliminar dirección de correo electrónico -email_deletion_desc=Esta dirección de correo electrónico y la información relacionada se eliminará de su cuenta. Las confirmaciones de Git hechas por esta dirección de correo electrónico permanecerán intactas. ¿Desea Continuar? +email_deletion=Retirar dirección de correo-e +email_deletion_desc=Esta dirección de correo electrónico y la información relacionada se retirará de su cuenta. Las confirmaciones de Git hechas por esta dirección de correo electrónico permanecerán intactas. ¿Desea Continuar? email_deletion_success=La dirección de correo electrónico ha sido eliminada. theme_update_success=Su tema fue actualizado. theme_update_error=El tema seleccionado no existe. @@ -789,7 +789,7 @@ add_email_success=La nueva dirección de correo electrónico ha sido añadida. email_preference_set_success=La preferencia de correo electrónico se ha establecido correctamente. add_openid_success=La nueva dirección OpenID ha sido añadida. keep_email_private=Ocultar dirección de correo electrónico -keep_email_private_popup=Su dirección de correo electrónico no se mostrará en su perfil y no será la predeterminada para las confirmaciones realizadas a través de la interfaz web, como las subidas de archivos, las ediciones y las confirmaciones de fusión. En su lugar, se utilizará una dirección especial %s para vincular las confirmaciones a tu cuenta. Esta opción no afectará a las confirmaciones existentes. +keep_email_private_popup=La dirección de correo electrónico no se mostrará en el perfil y no será la predeterminada para las confirmaciones realizadas a través de la interfaz web, como las subidas de archivos, las ediciones y las confirmaciones de fusión. En su lugar, se utilizará una dirección especial %s para vincular las confirmaciones a la cuenta. Esta opción no afectará a las confirmaciones existentes. openid_desc=OpenID le permite delegar la autenticación a un proveedor externo. manage_ssh_keys=Gestionar claves SSH @@ -840,8 +840,8 @@ add_key_success=La clave SSH "%s" ha sido añadida. add_gpg_key_success=La clave GPG "%s" ha sido añadida. add_principal_success=El certificado SSH principal "%s" ha sido añadido. delete_key=Eliminar -ssh_key_deletion=Eliminar clave SSH -gpg_key_deletion=Eliminar clave GPG +ssh_key_deletion=Retirar clave SSH +gpg_key_deletion=Retirar clave GPG ssh_principal_deletion=Eliminar principal de certificado SSH ssh_key_deletion_desc=Eliminando una clave SSH se revoca su acceso a su cuenta. ¿Continuar? gpg_key_deletion_desc=Eliminando una clave GPG se des-verifican los commits firmados con ella. ¿Continuar? @@ -875,7 +875,7 @@ delete_token=Eliminar access_token_deletion=Eliminar token de acceso access_token_deletion_desc=Eliminar un token revocará el acceso a su cuenta para las aplicaciones que lo usen. Esto no se puede deshacer. ¿Continuar? delete_token_success=El token ha sido eliminado. Las aplicaciones que lo usen ya no tienen acceso a su cuenta. -repo_and_org_access=Acceso al Repositorio y a la Organización +repo_and_org_access=Acceso al repositorio y a la organización permissions_public_only=Sólo público permissions_access_all=Todo (público, privado y limitado) select_permissions=Seleccionar permisos @@ -1023,6 +1023,8 @@ quota.applies_to_user = Las siguientes reglas de cuota se aplican a tu cuenta quota.applies_to_org = Las siguientes reglas de cuota se aplican a esta organización quota.rule.exceeded.helper = El tamaño total de los objetos para esta regla ha superado la cuota. +ssh_token_help_ssh_agent = o, si está usando un agente SSH (con la variable de entorno SSH_AUTH_SOCK): + [repo] owner=Propietario owner_helper=Algunas organizaciones pueden no aparecer en el menú desplegable debido a un límite máximo de recuento de repositorios. @@ -1628,8 +1630,8 @@ issues.lock.notice_3=- Siempre puede desbloquear esta incidencia de nuevo en el issues.unlock.notice_1=- Todos podrían comentar esta incidencia de nuevo. issues.unlock.notice_2=- Siempre puede bloquear esta incidencia de nuevo en el futuro. issues.lock.reason=Motivo del bloqueo -issues.lock.title=Bloquear conversación sobre esta incidencia. -issues.unlock.title=Desbloquear conversación sobre esta incidencia. +issues.lock.title=Bloquear conversación +issues.unlock.title=Desbloquear conversación issues.comment_on_locked=No puede comentar una incidencia bloqueada. issues.delete=Eliminar issues.delete.title=¿Eliminar esta incidencia? @@ -2288,7 +2290,7 @@ settings.packagist_api_token=Token de API settings.packagist_package_url=URL del paquete Packagist settings.deploy_keys=Claves de implementación settings.add_deploy_key=Añadir clave de implementación -settings.deploy_key_desc=Las claves de implementación tienen acceso de sólo lectura al repositorio. +settings.deploy_key_desc=Las claves de implementación pueden tener acceso de solo lectura o lectura y escritura al repositorio. settings.is_writable=Habilitar acceso de escritura settings.is_writable_info=Permitir que esta clave de implementación pueda hacer push a este repositorio. settings.no_deploy_keys=Aún no existen claves de implementación. @@ -2555,7 +2557,7 @@ branch.included=Incluida branch.create_new_branch=Crear rama desde la rama: branch.confirm_create_branch=Crear rama branch.warning_rename_default_branch=Estás renombrando la rama por defecto. -branch.rename_branch_to=Renombrar "%s" a: +branch.rename_branch_to=Renombrando rama "%s". branch.create_branch_operation=Crear rama branch.new_branch=Crear nueva rama branch.new_branch_from=`Crear nueva rama de "%s"` @@ -2740,6 +2742,39 @@ archive.nocomment = No es posible hacer comentarios porque el repositorio está sync_fork.branch_behind_one = Esta rama esta %[1]d cambios detrás de %[2]s sync_fork.branch_behind_few = Esta rama está %[1]d confirmaciones detrás de %[2]s +migrate.repo_desc_helper = Deje vacío para importar la descripción existente +commits.view_single_diff = Ver los cambios introducidos por la confirmación para este archivo +issues.filter_type.all_pull_requests = Todas las solicitudes de incorporación de cambios +issues.reaction.alt_many = %[1]s y %[2]d reaccionaron más que %[3]s. +comment.blocked_by_user = No es posible comentar porque ha sido bloqueado por el dueño del repositorio o el autor. +issues.summary_card_alt = El resumen de la incidencia titulada "%s" en el repositorio %s +pulls.editable_explanation = Esta incorporación de cambios permite ediciones de mantenedores. Tu puedes contribuir directamente a ella. +pulls.delete_after_merge.head_branch.is_protected = La cabeza de la rama que quiere borrar está protegida y no se puede eliminar. +pulls.delete_after_merge.head_branch.insufficient_branch = No tienes permiso para eliminar esa cabeza de la rama. +settings.default_update_style_desc = El modo por defecto utilizado para actualizar las solicitudes de incorporación de cambios que estén detrás de la rama base. +settings.wiki_branch_rename_success = La wiki de la rama del repositorio ha sido normalizada correctamente. +settings.wiki_branch_rename_failure = Hubo un error al normalizar el nombre de la rama de la wiki del repositorio. +release.hide_archive_links_helper = Ocultar el archivo de código generado automáticamente para este lanzamiento. Por ejemplo, si estás subiendo el tuyo propio. + +settings.event_action_recover = Recuperar +settings.event_action_success = Éxito +settings.event_action_success_desc = La ejecución de la acción se ejecutó con éxito. + +settings.event_header_action = Eventos de la ejecución de la acción +settings.event_action_failure = Fallo +settings.event_action_failure_desc = La ejecución de la acción terminó con fallos. +settings.event_action_recover_desc = La ejecución de la acción terminó con éxito después de que la última ejecución en el mismo flujo de trabajo fallara. +settings.sourcehut_builds.secrets_helper = Concede al trabajo acceso a los secretos de construcción (requiere el permiso SECRETS:RO) +settings.sourcehut_builds.access_token_helper = Token de acceso que tiene el permiso JOBS:RW. Genere un token de builds.sr.ht o un token de builds.sr.ht con acceso a secretos en meta.sr.ht. +settings.ignore_stale_approvals_desc = No contabilizar las aprobaciones realizadas en commits anteriores (revisiones obsoletas) para el cálculo del número de aprobaciones que la PR tiene. Esto no aplica si las revisiones obsoletas ya han sido descartadas. +settings.protect_branch_name_pattern_desc = Patrones de nombre de ramas protegidas. Véase la documentación para la sintaxis del patrón. Ejemplos: main, release/** +settings.enforce_on_admins = Aplicar esta regla para los administradores del repositorio +settings.matrix.access_token_helper = Se recomienda configurar una cuenta de Matrix dedicada para esto. El token de acceso puede ser obtenido desde el cliente web Element (en una pestaña privada/incógnito) > Menú de usuario (arriba izquierda) > Todos los ajustes > Ayuda & Acerca de > Avanzado > Token de acceso (a la derecha, debajo de URL del servidor). Cierra la pestaña privada/incógnito (desconectarse invalidaría el token). +settings.archive.mirrors_unavailable = Los espejos no están disponibles en repos archivados. +release.summary_card_alt = Tarjeta de resumen de una release titulada "%s" en el repositorio %s + +settings.matrix.room_id_helper = El ID de Sala puede ser obtenido desde el cliente web Element > Ajustes de Sala > Avanzado > ID de sala interna. Ejemplo: %s. + [graphs] component_loading = Cargando %s… component_loading_failed = No se pudo cargar %s @@ -2786,7 +2821,7 @@ settings.permission=Permisos settings.repoadminchangeteam=El administrador del repositorio puede añadir y eliminar el acceso a equipos settings.visibility=Visibilidad settings.visibility.public=Público -settings.visibility.limited=Limitado (visible solo para usuarios autenticados) +settings.visibility.limited=Limitado (visible solo para usuarios accedidos) settings.visibility.limited_shortname=Limitado settings.visibility.private=Privado (Visible sólo para miembros de la organización) settings.visibility.private_shortname=Privado @@ -2925,7 +2960,7 @@ dashboard.update_migration_poster_id=Actualizar ID de usuario en migraciones dashboard.git_gc_repos=Ejecutar la recolección de basura en los repositorios dashboard.resync_all_sshkeys=Actualiza el archivo '.ssh/authorized_keys' con claves SSH de Forgejo. dashboard.resync_all_sshprincipals=Actualiza el archivo '.ssh/authorized_principals' con los principales del certificado SSH de Forgejo. -dashboard.resync_all_hooks=Resincronizar los hooks de pre-recepción, actualización y post-recepción de todos los repositorios +dashboard.resync_all_hooks=Resincronizar los hooks de todos los repositorios (pre-recepción, actualización, post-recepción, procesamiento de recepción, etc.) dashboard.reinit_missing_repos=Reiniciar todos los repositorios Git faltantes de los que existen registros dashboard.sync_external_users=Sincronizar datos de usuario externo dashboard.cleanup_hook_task_table=Limpiar la tabla hook_task @@ -2965,7 +3000,7 @@ dashboard.update_checker=Buscador de actualizaciones dashboard.delete_old_system_notices=Borrar todos los avisos antiguos del sistema de la base de datos dashboard.gc_lfs=Recoger basura meta-objetos LFS dashboard.stop_zombie_tasks=Detener tareas zombie -dashboard.stop_endless_tasks=Detener tareas interminables +dashboard.stop_endless_tasks=Detiene tareas de acciones interminables dashboard.cancel_abandoned_jobs=Cancelar trabajos abandonados dashboard.start_schedule_tasks=Iniciar tareas programadas dashboard.sync_branch.started=Inició la sincronización de ramas @@ -2998,7 +3033,7 @@ users.edit_account=Editar cuenta de usuario users.max_repo_creation=Número máximo de repositorios users.max_repo_creation_desc=(Introduzca -1 para usar el límite por defecto global.) users.is_activated=Cuenta de usuario activada -users.prohibit_login=Suspender cuenta +users.prohibit_login=Cuenta suspendida users.is_admin=Cuenta adminstrador users.is_restricted=Cuenta restringida users.allow_git_hook=Puede crear Git hooks @@ -3010,8 +3045,8 @@ users.delete_account=Eliminar cuenta de usuario users.cannot_delete_self=No puedes eliminarte a ti mismo users.still_own_repo=Este usuario todavía posee uno o más depósitos. Eliminar o transferir estos repositorios primero. users.still_has_org=Este usuario es un miembro de una organización. Primero retire el usuario de cualquier organización. -users.purge=Borrar usuario -users.purge_help=Borrar forzosamente el usuario y cualquier repositorio, organización y paquete propiedad del usuario. Todos los comentarios también serán borrados. +users.purge=Purgar usuario +users.purge_help=Borrar forzosamente el usuario y cualquier repositorio, organización y paquete propiedad del usuario. Todos los comentarios e incidencias publicados por este usuario también serán borrados. users.still_own_packages=Este usuario todavía posee uno o más paquetes, elimina estos paquetes primero. users.deletion_success=La cuenta de usuario ha sido eliminada. users.reset_2fa=Reiniciar 2FA @@ -3020,7 +3055,7 @@ users.list_status_filter.reset=Reiniciar users.list_status_filter.is_active=Activo users.list_status_filter.not_active=Inactivo users.list_status_filter.is_admin=Administrador -users.list_status_filter.not_admin=Sin Admin +users.list_status_filter.not_admin=No admin users.list_status_filter.is_restricted=Restringido users.list_status_filter.not_restricted=No restringido users.list_status_filter.is_prohibit_login=Prohibido el inicio de sesión @@ -3029,7 +3064,7 @@ users.list_status_filter.is_2fa_enabled=2FA habilitado users.list_status_filter.not_2fa_enabled=2FA deshabilitado users.details=Detalles del usuario -emails.email_manage_panel=Gestion de Correo del Usuario +emails.email_manage_panel=Administrar direcciones de correo electrónico del usuario emails.primary=Principal emails.activated=Activado emails.filter_sort.email=Correo electrónico @@ -3039,15 +3074,15 @@ emails.filter_sort.name_reverse=Nombre de usuario (invertir) emails.updated=Email actualizado emails.not_updated=Error al actualizar la dirección de correo electrónico solicitada: %v emails.duplicate_active=Esta dirección de correo está asignada a un usuario diferente. -emails.change_email_header=Actualizar Propiedades de Correo +emails.change_email_header=Actualizar propiedades del correo -orgs.org_manage_panel=Gestión de organizaciones +orgs.org_manage_panel=Administrar organizaciones orgs.name=Nombre orgs.teams=Equipos orgs.members=Miembros orgs.new_orga=Nueva organización -repos.repo_manage_panel=Gestión de repositorios +repos.repo_manage_panel=Administrar repositorios repos.unadopted=Repositorios no adoptados repos.unadopted.no_more=No se encontraron repositorios no adoptados. repos.owner=Propietario @@ -3057,7 +3092,7 @@ repos.issues=Incidencias repos.size=Tamaño repos.lfs_size=Tamaño LFS -packages.package_manage_panel=Gestión de paquetes +packages.package_manage_panel=Administrar paquetes packages.total_size=Tamaño total: %s packages.unreferenced_size=Tamaño sin referencia: %s packages.cleanup=Limpiar datos caducados @@ -3080,7 +3115,7 @@ systemhooks.desc=Los webhooks automáticamente hacen peticiones HTTP POST a un s systemhooks.add_webhook=Añadir Webhook del Sistema systemhooks.update_webhook=Actualizar Webhook del Sistema -auths.auth_manage_panel=Gestión de origen de autenticación +auths.auth_manage_panel=Administrar orígenes de autenticación auths.new=Añadir origen de autenticación auths.name=Nombre auths.type=Tipo @@ -3095,21 +3130,21 @@ auths.host=Servidor auths.port=Puerto auths.bind_dn=Bind DN auths.bind_password=Contraseña Bind -auths.user_base=Base de búsqueda de usuarios +auths.user_base=Base de búsqueda del usuario auths.user_dn=DN de Usuario auths.attribute_username=Atributo nombre de usuario auths.attribute_username_placeholder=Dejar vacío para usar el nombre de usuario introducido en Forgejo. auths.attribute_name=Atributo nombre auths.attribute_surname=Atributo apellido -auths.attribute_mail=Atributo correo electrónico -auths.attribute_ssh_public_key=Atributo Clave Pública SSH -auths.attribute_avatar=Atributo del avatar -auths.attributes_in_bind=Obtener atributos en el contexto de Bind DN +auths.attribute_mail=Atributo correo-e +auths.attribute_ssh_public_key=Atributo clave pública SSH +auths.attribute_avatar=Atributo avatar +auths.attributes_in_bind=Obtiene atributos en el contexto de bind DN auths.allow_deactivate_all=Permitir un resultado de búsqueda vacío para desactivar todos los usuarios auths.use_paged_search=Usar búsqueda paginada auths.search_page_size=Tamaño de página auths.filter=Filtro de usuario -auths.admin_filter=Filtro de aministrador +auths.admin_filter=Filtro de administrador auths.restricted_filter=Filtro restringido auths.restricted_filter_helper=Dejar en blanco para no establecer ningún usuario como restringido. Utilice un asterisco ('*') para establecer todos los usuarios que no coincidan con el filtro de administración como restringido. auths.verify_group_membership=Verificar pertenencia al grupo en LDAP (dejar el filtro vacío para saltar) @@ -3123,15 +3158,15 @@ auths.ms_ad_sa=Atributos de búsqueda de MS AD auths.smtp_auth=Tipo de autenticación SMTP auths.smtphost=Servidor SMTP auths.smtpport=Puerto SMTP -auths.allowed_domains=Dominios Permitidos -auths.allowed_domains_helper=Dejar vacío para permitir todos los dominios. Separa múltiples dominios con una coma (','). +auths.allowed_domains=Dominios permitidos +auths.allowed_domains_helper=Dejar vacío para permitir todos los dominios. Separa múltiples dominios con una coma (","). auths.skip_tls_verify=Omitir la verificación TLS auths.force_smtps=Forzar SMTPS auths.force_smtps_helper=SMTPS se utiliza siempre en el puerto 465. Establezca esto para forzar SMTPS en otros puertos. (De lo contrario, STARTTLS se utilizará en otros puertos si es soportado por el host.) auths.helo_hostname=Nombre de anfitrión HELO auths.helo_hostname_helper=Nombre de anfitrión enviado con HELO. Déjelo vacío para enviar el nombre de anfitrión actual. auths.disable_helo=Desactivar HELO -auths.pam_service_name=Nombre del Servicio PAM +auths.pam_service_name=Nombre del servicio PAM auths.pam_email_domain=Dominio de correo de PAM (opcional) auths.oauth2_provider=Proveedor OAuth2 auths.oauth2_icon_url=URL de icono @@ -3188,23 +3223,23 @@ auths.unable_to_initialize_openid=No se puede inicializar el proveedor de OpenID auths.invalid_openIdConnectAutoDiscoveryURL=URL de auto descubrimiento no válida (esta debe ser una URL válida comenzando con http:// o https://) config.server_config=Configuración del servidor -config.app_name=Título del sitio +config.app_name=Título de la instancia config.app_ver=Versión de Forgejo -config.app_url=URL base de Forgejo +config.app_url=URL base config.custom_conf=Ruta del fichero de configuración -config.custom_file_root_path=Ruta raíz de los archivos personalizada -config.domain=Dominio del Servidor -config.offline_mode=Modo offline -config.disable_router_log=Deshabilitar Log del Router -config.run_user=Ejecutar como usuario +config.custom_file_root_path=Ruta raíz del archivo personalizado +config.domain=Dominio del servidor +config.offline_mode=Modo local +config.disable_router_log=Inhabilitar bitácora de enrutado +config.run_user=Usuario a ejecutar como config.run_mode=Modo de ejecución config.git_version=Versión de Git -config.app_data_path=Ruta de datos de Forgejo -config.repo_root_path=Ruta del Repositorio +config.app_data_path=Ruta de datos de App +config.repo_root_path=Ruta del repositorio raíz config.lfs_root_path=Ruta raíz de LFS -config.log_file_root_path=Ruta de ficheros de registro -config.script_type=Tipo de Script -config.reverse_auth_user=Autenticación Inversa de Usuario +config.log_file_root_path=Ruta bitácora +config.script_type=Tipo de guion +config.reverse_auth_user=Autenticación inversa de proxy del usuario config.ssh_config=Configuración SSH config.ssh_enabled=Habilitado @@ -3214,16 +3249,16 @@ config.ssh_port=Puerto config.ssh_listen_port=Puerto de escucha config.ssh_root_path=Ruta raíz config.ssh_key_test_path=Ruta de la clave de prueba -config.ssh_keygen_path=Ruta del generador de claves ('ssh-keygen') -config.ssh_minimum_key_size_check=Tamaño mínimo de la clave de verificación +config.ssh_keygen_path=Ruta del generador de claves ("ssh-keygen") +config.ssh_minimum_key_size_check=Comprobante de tamaño de clave mínimo config.ssh_minimum_key_sizes=Tamaños de clave mínimos config.lfs_config=Configuración LFS config.lfs_enabled=Habilitado config.lfs_content_path=Ruta de contenido LFS -config.lfs_http_auth_expiry=Caducidad de la autentificación HTTP LFS +config.lfs_http_auth_expiry=Caducidad de la autenticación HTTP LFS -config.db_config=Configuración de la Base de Datos +config.db_config=Configuración de base de datos config.db_type=Tipo config.db_host=Host config.db_name=Nombre @@ -3233,99 +3268,99 @@ config.db_ssl_mode=SSL config.db_path=Ruta config.service_config=Configuración del servicio -config.register_email_confirm=Requerir confirmación de correo electrónico para registrarse -config.disable_register=Deshabilitar auto-registro -config.allow_only_internal_registration=Permitir el registro solo desde Forgejo -config.allow_only_external_registration=Permitir el registro únicamente a través de servicios externos -config.enable_openid_signup=Habilitar el auto-registro con OpenID -config.enable_openid_signin=Habilitar el inicio de sesión con OpenID -config.show_registration_button=Mostrar Botón de Registro -config.require_sign_in_view=Requerir inicio de sesión obligatorio para ver páginas -config.mail_notify=Habilitar las notificaciones por correo electrónico +config.register_email_confirm=Requerir confirmación de correo-e para registrarse +config.disable_register=Inhabilitar auto-registro +config.allow_only_internal_registration=Concede registro solo por medio de Forgejo +config.allow_only_external_registration=Concede registro solo a través de servicios externos +config.enable_openid_signup=Habilitar auto-registro con OpenID +config.enable_openid_signin=Habilitar inicio de sesión con OpenID +config.show_registration_button=Mostrar botón de registro +config.require_sign_in_view=Requiere inicio de sesión para ver contenido +config.mail_notify=Habilitar notificaciones por correo-e config.enable_captcha=Activar CAPTCHA -config.active_code_lives=Habilitar Vida del Código -config.reset_password_code_lives=Caducidad del código de recuperación de cuenta -config.default_keep_email_private=Ocultar direcciones de correo electrónico por defecto -config.default_allow_create_organization=Permitir la creación de organizaciones por defecto +config.active_code_lives=Código de activación del tiempo de vida +config.reset_password_code_lives=Código de recuperación del tiempo de vida +config.default_keep_email_private=Ocultar direcciones de correo-e por defecto +config.default_allow_create_organization=Concede la creación de organizaciones por defecto config.enable_timetracking=Habilitar seguimiento de tiempo config.default_enable_timetracking=Habilitar seguimiento de tiempo por defecto config.allow_dots_in_usernames = Permite utilizar puntos en los nombres de usuario. No tiene efecto sobre cuentas existentes. config.default_allow_only_contributors_to_track_time=Deje que solo los colaboradores hagan un seguimiento del tiempo -config.no_reply_address=Dominio de correos electrónicos ocultos -config.default_visibility_organization=Visibilidad por defecto para nuevas organizaciones +config.no_reply_address=Dominio de correo-e ocultos +config.default_visibility_organization=Visibilidad por defecto para organizaciones nuevas config.default_enable_dependencies=Habilitar dependencias de incidencias por defecto config.webhook_config=Configuración de Webhooks -config.queue_length=Tamaño de Cola de Envío -config.deliver_timeout=Timeout de Entrega -config.skip_tls_verify=Saltar verificación TLS +config.queue_length=Longitud de cola +config.deliver_timeout=Vencimiento de entrega +config.skip_tls_verify=Omitir verificación TLS -config.mailer_config=Configuración del servidor de correo +config.mailer_config=Configuración del cartero config.mailer_enabled=Activado config.mailer_enable_helo=Habilitar HELO config.mailer_name=Nombre config.mailer_protocol=Protocolo -config.mailer_smtp_addr=Dirección SMTP +config.mailer_smtp_addr=Hospedaje SMTP config.mailer_smtp_port=Puerto SMTP config.mailer_user=Usuario config.mailer_use_sendmail=Usar Sendmail config.mailer_sendmail_path=Ruta de Sendmail config.mailer_sendmail_args=Argumentos adicionales por Sendmail -config.mailer_sendmail_timeout=Tiempo de espera de Sendmail +config.mailer_sendmail_timeout=Vencimiento de Sendmail config.mailer_use_dummy=Dummy config.test_email_placeholder=Correo electrónico (ej. test@ejemplo.com) -config.send_test_mail=Enviar prueba de correo +config.send_test_mail=Enviar prueba de correo-e config.send_test_mail_submit=Enviar -config.test_mail_failed=Fallo al enviar un correo electrónico de prueba a "%s": %v -config.test_mail_sent=Se ha enviado un correo electrónico de prueba a "%s". +config.test_mail_failed=Fallo al enviar una prueba de correo-e a «%s»: %v +config.test_mail_sent=Se ha enviado un correo-e de prueba a «%s». config.oauth_config=Configuración OAuth config.oauth_enabled=Activado -config.cache_config=Configuración de la Caché -config.cache_adapter=Adaptador de la Caché -config.cache_interval=Intervalo de la Caché -config.cache_conn=Conexión de la Caché -config.cache_item_ttl=Período de vida para elementos de caché +config.cache_config=Configuración de caché +config.cache_adapter=Adaptador de caché +config.cache_interval=Intervalo de caché +config.cache_conn=Conexión de caché +config.cache_item_ttl=TTL de elemento caché -config.session_config=Configuración de la Sesión -config.session_provider=Proveedor de la Sesión -config.provider_config=Configuración del Proveedor -config.cookie_name=Nombre de la Cookie -config.gc_interval_time=Intervalo de tiempo del GC -config.session_life_time=Tiempo de Vida de la Sesión -config.https_only=Sólo HTTPS +config.session_config=Configuración de sesión +config.session_provider=Proveedor de sesión +config.provider_config=Configuración de proveedor +config.cookie_name=Nombre de cookie +config.gc_interval_time=Tiempo de intervalo GC +config.session_life_time=Tiempo de vida de sesión +config.https_only=Solo HTTPS config.cookie_life_time=Tiempo de Vida de la Cookie config.picture_config=Configuración de imagen y avatar config.picture_service=Servicio de Imágen config.disable_gravatar=Desactivar Gravatar -config.enable_federated_avatar=Habilitar Avatares Federados +config.enable_federated_avatar=Habilitar avatares federados config.git_config=Configuración de Git -config.git_disable_diff_highlight=Desactivar resaltado de sintaxis del Diff -config.git_max_diff_lines=Líneas de Diff máximas (por un solo archivo) -config.git_max_diff_line_characters=Carácteres de Diff máximos (para una sola línea) -config.git_max_diff_files=Máximo de archivos de Diff (que se mostrarán) +config.git_disable_diff_highlight=Inhabilitar resaltado de diff de sintaxis +config.git_max_diff_lines=Líneas de diff máximas por archivo +config.git_max_diff_line_characters=Caracteres de diff máx por línea +config.git_max_diff_files=Diff de archivos máxima mostrada config.git_gc_args=Argumentos de GC -config.git_migrate_timeout=Tiempo de espera de migración -config.git_mirror_timeout=Tiempo de espera de actualización de réplicas -config.git_clone_timeout=Tiempo de espera de operación de clones -config.git_pull_timeout=Tiempo de espera de operación de pull -config.git_gc_timeout=Tiempo de espera de operación de GC +config.git_migrate_timeout=Vencimiento de migración +config.git_mirror_timeout=Vencimiento de actualización de réplica +config.git_clone_timeout=Vencimiento de operación de clonado +config.git_pull_timeout=Vencimiento de operación de pull +config.git_gc_timeout=Vencimiento de operación de GC -config.log_config=Configuración del Log +config.log_config=Configuración de bitácora config.logger_name_fmt=Registro: %s config.disabled_logger=Desactivado config.access_log_mode=Modo de registro del Acceso -config.access_log_template=Plantilla de registro de acceso +config.access_log_template=Plantilla de bitácora de acceso config.xorm_log_sql=Registrar SQL config.set_setting_failed=Error al configurar %s monitor.stats=Estadísticas -monitor.cron=Tareas de Cron +monitor.cron=Tareas de cron monitor.name=Nombre monitor.schedule=Agenda monitor.next=Siguiente @@ -3351,9 +3386,9 @@ monitor.queue.type=Tipo monitor.queue.exemplar=Ejemplo monitor.queue.numberworkers=Número de trabajadores monitor.queue.activeworkers=Trabajadores activos -monitor.queue.maxnumberworkers=Número máximo de trabajadores +monitor.queue.maxnumberworkers=Nº máx de trabajadores monitor.queue.numberinqueue=Número en cola -monitor.queue.review_add=Revisar / Añadir Trabajadores +monitor.queue.review_add=Revisar / Añadir trabajadores monitor.queue.settings.title=Ajustes del grupo monitor.queue.settings.desc=Los grupos de trabajadores crecen dinámicamente en respuesta al bloqueo de cola de sus trabajadores. monitor.queue.settings.maxnumberworkers=Número máximo de trabajadores @@ -3364,10 +3399,10 @@ monitor.queue.settings.changed=Ajustes actualizados monitor.queue.settings.remove_all_items=Eliminar todo monitor.queue.settings.remove_all_items_done=Todos los elementos en la cola han sido eliminados. -notices.system_notice_list=Notificaciones del Sistema -notices.view_detail_header=Ver detalles de notificación +notices.system_notice_list=Notificaciones del sistema +notices.view_detail_header=Detalles de notificación notices.operations=Operaciones -notices.select_all=Sleccionar todo +notices.select_all=Seleccionar todo notices.deselect_all=Deseleccionar todo notices.inverse_selection=Selección inversa notices.delete_selected=Eliminar seleccionado @@ -3397,6 +3432,23 @@ config.app_slogan = Eslogan de la instancia dashboard.sync_tag.started = Sincronización de etiquetas iniciada +dashboard.sync_repo_tags = Sincronizar etiquetas de Git con la base de datos +users.block.description = Bloquear a este usuario para que no pueda interactuar a través de su cuenta e impedirle iniciar sesión. +users.admin.description = Otorgar a este usuario acceso completo a todas las funciones administrativas disponibles a través de la interfaz de usuario web y en la API. +users.restricted.description = Solo permitir interactuar con los repositorios y organizaciones en los que el usuario ha sido añadido como colaborador. Esto previene el acceso a repositorios públicos en esta instancia. +users.local_import.description = Permitir la importación de repositorios desde el sistema de archivos local del servidor. Esto puede suponer un problema de seguridad. +packages.cleanup.success = Se eliminaron correctamente los datos caducados +auths.default_domain_name = Nombre de dominio por defecto usado para la dirección de correo +config.cache_test_slow = Prueba de caché exitosa, pero la respuesta es lenta: %s. +config.cache_test_succeeded = Prueba de caché exitosa, se obtuvo una respuesta en %s. +config.open_with_editor_app_help = Los editores disponibles para "Abrir con" en el menú de clonado. Si se deja vacío, se utilizan los valores por defecto. Expandir para ver estos valores. +self_check.database_collation_mismatch = Se espera que la base de datos use intercalación: %s +self_check.database_collation_case_insensitive = La base de datos está usando intercalación %s, que es una intercalación insensible. Aunque Forgejo podría funcionar, puede darse algún caso extraño en el que no funcione como se espera. +self_check.database_inconsistent_collation_columns = La base de datos está usando intercalación %s, pero estas columnas están usando intercalaciones desparejadas. Esto puede causar algunos problemas inesperados. +self_check.database_fix_mysql = Para usuarios de MySQL/MariaDB, podrían usar el comando "forgejo doctor convert" para arreglar los problemas de intercalación, o también podrían arreglarlos utilizando consultas SQL manuales, como "ALTER ... COLLATE ...". + +config.cache_test_failed = Incorrecto al probar la caché: %v. + [action] create_repo=creó el repositorio %s rename_repo=repositorio renombrado de %[1]s a %[3]s @@ -3743,8 +3795,8 @@ runs.no_runs=El flujo de trabajo no tiene ejecuciones todavía. workflow.disable=Desactivar flujo de trabajo workflow.disable_success=Flujo de trabajo "%s" desactivado exitosamente. -workflow.enable=Activar flujo de trabajo -workflow.enable_success=Flujo de trabajo '%s' habilitado con éxito. +workflow.enable=Habilitar flujo +workflow.enable_success=Flujo «%s» habilitado correctamente. workflow.disabled=El flujo de trabajo está deshabilitado. need_approval_desc=Necesita aprobación para ejecutar flujos de trabajo para el pull request del fork. @@ -3777,11 +3829,14 @@ workflow.dispatch.input_required = Se requiere valor para la entrada "%s". workflow.dispatch.trigger_found = Este flujo de trabajo tiene un disparador de eventos workflow_dispatch. workflow.dispatch.warn_input_limit = Sólo se muestran las primeras %d entradas. +runs.no_workflows.help_write_access = ¿No sabes cómo empezar con Forgejo Actions? Comprueba la guía de inicio rápido en la documentación de usuario para escribir tu primer workflow, luego configura un runner de Forgejo para ejecutar tus trabajos. +runs.no_workflows.help_no_write_access = Para aprender sobre Forgejo Actions, véase la documentación. + [projects] type-1.display_name=Proyecto individual type-2.display_name=Proyecto de repositorio type-3.display_name=Proyecto de organización -deleted.display_name = Proyecto borrado +deleted.display_name = Proyecto eliminado [git.filemode] changed_filemode=%[1]s → %[2]s @@ -3844,6 +3899,9 @@ issues.write = Escritura: Cerrar incidencias y gestion de metadatos como packages.write = Escritura: Publicar y eliminar paquetes asignados al repositorio. +actions.read = Leer: visualizar ejecuciones del flujo de trabajo y sus logs. +actions.write = Escribir: Ejecutar, reiniciar y cancelar flujos de trabajo. Gestionar la delegación de confianza a los publicadores de pull requests. + [munits.data] eib = EiB gib = GiB @@ -3851,4 +3909,7 @@ pib = PiB kib = KiB tib = TiB mib = MiB -b = B \ No newline at end of file +b = B + +[translation_meta] +test = Did you know that the Garoé, the sacred tree of El Hierro in the Canary Islands, was essentially a natural water fountain? :) \ No newline at end of file diff --git a/options/locale/locale_et.ini b/options/locale/locale_et.ini index f62360f5ea..f1dfc1be6e 100644 --- a/options/locale/locale_et.ini +++ b/options/locale/locale_et.ini @@ -33,7 +33,7 @@ toggle_menu = Lülita menüü sisse/välja more_items = Rohkem objekte email = E-posti aadress password = Salasõna -access_token = Tunnusluba +access_token = Juurdepääsu tunnusluba re_type = Kinnita salasõna twofa = Kahefaktoriline autentimine twofa_scratch = Kahefaktoriline kriipsukood @@ -67,7 +67,7 @@ all = Kõik sources = Allikad mirror = Peegelpilt mirrors = Peegelpildid -forks = Harud +forks = Koodiharud activities = Tegevused pull_requests = Päringud koodi mestimiseks issues = Veahaldus @@ -92,7 +92,7 @@ copy = Kopeeri copy_url = Kopeeri võrguaadress copy_hash = Kopeeri räsi copy_content = Kopeeri sisu -copy_branch = Kopeeri haru nimi +copy_branch = Kopeeri alamharu nimi copy_success = Kopeeritud! copy_error = Kopeerimine ei õnnestunud copy_type_unsupported = Seda failitüüpi ei saa kopeerida @@ -124,8 +124,8 @@ filter = Filter filter.clear = Tühjenda filtrid filter.is_archived = Arhiveeritud filter.not_archived = Arhiveerimata -filter.is_fork = -filter.not_fork = +filter.is_fork =Koodiharud +filter.not_fork =Pole koodiharud filter.is_mirror = Peegelpildid filter.not_mirror = Pole peegelpilte filter.is_template = Mallid @@ -142,6 +142,8 @@ captcha = Robotilõks unpin = Lõpeta esiletõstmine powered_by = Siin on kasutusel %s +collaborative = Koostöö + [search] search = Otsi… fuzzy = Hägus @@ -156,7 +158,7 @@ team_kind = Otsi tiime… code_kind = Otsi koodi… package_kind = Otsi pakette… project_kind = Otsi projekte… -branch_kind = Otsi harusid… +branch_kind = Otsi alamharusid… commit_kind = Otsi kommiteid… runner_kind = Otsi jooksjaid… no_results = Sobivaid tulemusi ei leitud. @@ -334,25 +336,52 @@ offline_mode.description = Lülitage kolmandate osapoolte sisuedastusvõrgud vä password_algorithm = Salasõna räsialgoritm invalid_password_algorithm = Vigane salasõna räsialgoritm +invalid_repo_path = Tarkvarahoidla juurkaust on vigane: %v +invalid_app_data_path = Rakenduse andmete asukoht on vigane: %v + [auth] allow_password_change = Eelda, et kasutajad muudavad oma salasõna (soovitatav) forgot_password_title = Ununenud salasõna must_change_password = Muuda oma salasõna forgot_password = Kas salasõna ununes? +verify = Verifitseeri +openid_connect_submit = Ühenda + [mail] password_change.subject = Sinu salasõna on muutunud password_change.text_1 = Sinu kasutajakonto salasõna on just muutunud. totp_disabled.text_1 = Lisaautentimine ehk ajapõhise salasõna (TOTP) kasutamine on sinu kasutajakontol just välja lülitatud. +release.note = Märkus: +release.downloads = Allalaadimised: +repo.transfer.to_you = sina + [form] Retype = Korda salasõna password_not_match = Salasõnad ei klapi. Password = Salasõna username_password_incorrect = Kassutajanimi või salasõna pole õige. required_prefix = Sisendi alguses peab olema „&s“ -To = Haru nimi -NewBranchName = Haru uus nimi +To = Alamharu nimi +NewBranchName = Alamharu uus nimi + +UserName = Kasutajanimi +Description = Kirjeldus +Pronouns = Asesõnad +Biography = Biograafia +Website = Veebisait +Location = Asukoht +Content = Sisu + +password_complexity = Salasõna ei vasta keerukuse reeglitele: +password_lowercase_one = Peaks olema vähemalt üks väiketäht +password_uppercase_one = Peaks olema vähemalt üks suurtäht +password_digit_one = Peaks olema vähemalt üks number +password_special_one = Peaks olema vähemalt üks erimärk (kirjavahemärk, sulg, jutumärk, jne) +enterred_invalid_password = Sinu sisestatud salasõna pole korrektne. +unset_password = Siselogiv kasutaja pole lisanud oma kontole salasõna. +target_branch_not_exist = Sihiks võetud alamharu pole olemas. [settings] retype_new_password = Korda uut salasõna @@ -361,7 +390,56 @@ change_password_success = Sina salasõna on nüüd muudetud. Edaspidi kasuta sis update_password = Muuda salasõna old_password = Senine salasõna new_password = Uus salasõna -comment_type_group_branch = Koodiharu +comment_type_group_branch = Alamharu + +profile = Profiil +account = Kasutajakonto +appearance = Välimus +security = Turvalisus +avatar = Tunnuspilt +applications = Rakendused +orgs = Organisatsioonid +repos = Koodihoidlad +organization = Organisatsioonid +website = Veebisait +location = Asukoht +pronouns = Asesõnad +pronouns_unspecified = Määratlemata +cancel = Katkesta +language = Keel +ui = Kujundus +hints = Vihjed +comment_type_group_reference = Viide +comment_type_group_label = Silt +comment_type_group_milestone = Vahe-eesmärk +comment_type_group_assignee = Määratud kasutajale +comment_type_group_title = Pealkiri +comment_type_group_deadline = Tähtaeg +comment_type_group_dependency = Sõltuvus +comment_type_group_project = Projekt +privacy = Privaatsus +primary = Esmane +activated = Aktiveeritud +delete_email = Eemalda +gpg_key_verify = Verifitseeri +gpg_token = Tunnusluba +ssh_key_verify = Verifitseeri +ssh_token = Tunnusluba +subkeys = Alamvõtmed +key_content = Sisu +principal_content = Sisu +delete_key = Eemalda +can_read_info = Lugemine +can_write_info = Kirjutamine +delete_token = Kustuta +permission_read = Lugemine +permissions_list = Õigused: +save_application = Salvesta +oauth2_application_edit = Muuda + +change_password = Salasõna muutmine +password_change_disabled = Kohalikus serveris mitteleiduvad kasutajad ei saa oma salasõna Forgejo kasutajaliidesest muuta. +email_desc = Sinu põhilist e-posti aadressi kasutatakse teavitusteks, salasõna taastamiseks ning kui ta pole peidetud, siis ka veebipõhisteks toiminguteks gitiga. [repo] mirror_sync_on_commit = Sünkrooni sissekannete tegemisel @@ -374,7 +452,7 @@ mirror_password_help = Salvestatud salasõna kustutamiseks muuda kasutajanime. mirror_address = Klooni võrguaadressilt mirror_password_blank_placeholder = (Seadistamata) commits.message = Sõnum -commits.search_all = Kõik koodiharud +commits.search_all = Kõik alamharu commits.author = Autor commits.browse_further = Sirvi edasi commits.renamed_from = Nimi muudetud, vana nimi oli „%s“ @@ -382,7 +460,7 @@ commits.date = Kuupäev commits.older = Vanemad commits.newer = Uuemad commitstatus.error = Viga -commits.search_branch = See koodiharu +commits.search_branch = See alamharu projects = Projektid commitstatus.failure = Tõrge commitstatus.pending = Ootel @@ -392,32 +470,102 @@ issues.filter_sort.moststars = Enim tärne issues.choose.get_started = Alustame issues.start_tracking_short = Käivita taimer issues.filter_sort.feweststars = Kõike vähem tärne -rss.must_be_on_branch = RSS-voo jaoks pead asuma koodiharus. -all_branches = Kõik koodiharud -default_branch = Vaikimisi koodiharu +rss.must_be_on_branch = RSS-voo jaoks pead asuma alamharus. +all_branches = Kõik alamharud +default_branch = Vaikimisi alamharu default_branch_label = vaikimisi -code.desc = Ligipääs lähtekoodile, failidele, sissekannetele ja koodiharudele. -filter_branch_and_tag = Filtreeri koodiharu või sildi alusel -branches = Koodiharud -n_branch_one = %s koodiharu -n_branch_few = %s koodiharu -commit_graph.select = Vali koodiharud -commit.contained_in_default_branch = See sissekanne on vaikimisi koodiharu osa -editor.new_branch_name_desc = Koodiharu uus nimi… -commits.nothing_to_compare = Need koodiharud on võrdsed. -issues.no_ref = Ühtegi koodiharu/silti pole määratud -pulls.merged_info_text = Koodiharu %s võid nüüd kustutada. -pulls.update_branch_success = Koodiharu uuendamine õnnestus -pulls.update_not_allowed = Sul pole õigust koodiharu uuendada +code.desc = Ligipääs lähtekoodile, failidele, sissekannetele ja alamharudele. +filter_branch_and_tag = Filtreeri alamharu või sildi alusel +branches = Alamharud +n_branch_one = %s alamharu +n_branch_few = %s alamharu +commit_graph.select = Vali alamharud +commit.contained_in_default_branch = See sissekanne on vaikimisi alamharu osa +editor.new_branch_name_desc = Alamharu uus nimi… +commits.nothing_to_compare = Need alamharud on võrdsed. +issues.no_ref = Ühtegi alamharu/silti pole määratud +pulls.merged_info_text = Selle alamharu %s võid nüüd kustutada. +pulls.update_branch_success = Alamharu uuendamine õnnestus +pulls.update_not_allowed = Sul pole õigust alamharu uuendada pull.deleted_branch = (kustutatud):%s -settings.branches.update_default_branch = Uuenda vaikimisi koodiharu +settings.branches.update_default_branch = Uuenda vaikimisi alamharu settings.branches.add_new_rule = Lisa uus reegel -settings.event_create_desc = Koodiharu või silt on loodud. -settings.event_delete_desc = Koodiharu või silt on kustutatud. -settings.branches = Kooduharud +settings.event_create_desc = Alamharu või silt on loodud. +settings.event_delete_desc = Alamharu või silt on kustutatud. +settings.branches = Alamharud settings.protected_branch.save_rule = Salvesta reegel settings.protected_branch.delete_rule = Kustuta reegel +editor.add_file = Lisa fail +editor.or = või +editor.cancel_lower = Katkesta +editor.add_tmpl.filename = failinimi +pulls.editable = Muudetav + +fork_repo = Tee lähtekoodihoidlast uus koodiharu +fork_from = Tee koodiharu allikast +already_forked = Sa juba oled siit teinud koodiharu: %s +fork_to_different_account = Tee koodihatu teisele kasutajakontole +fork_visibility_helper = Lähtekoodihoidla koodiharu nähtavust ei saa muuta. +fork_branch = Alamharu, millest tahad kloonid koodiharu +mirror_denied_combination = Salasõnapõhist ja avaliku võtme põhist autentimist ei saa samal ajal kasutada. +forks = Koodharud +tree_path_not_found.branch = Asukohta „%[1]s“ pole olemas alamharus „%[2]s“ +template.git_content = Giti sisu (vaikimisi alamharu) +sync_fork.button = Sünkrooni +forked_from = koodiharu allikast +fork_from_self = Sa ei saa endale kuuluvast lähtekoodi hoidlast koodiharu teha. +fork_guest_user = Logi sisse sellest lähtekoodi hoidlast koodiharu tegemiseks. +fork = Tee koodiharu +commit.load_referencing_branches_and_tags = Laadi alamharud ja sildid, mis viitavad sellele sissekandele +editor.must_be_on_a_branch = Selle faili muutmiseks või muudatuste pakkumiseks pead asuma antud alamharus. +editor.create_new_branch_np = Loo selle sissekande jaoks uus alamharu. +editor.new_branch_name = Anna selle sissekande jaoks loodud uuele alamharule nimi +editor.branch_does_not_exist = Selles lähtekoodihoidlas pole olemas alamharu nimega „%s“. +editor.branch_already_exists = Selles lähtekoodihoidlas juba on olemas alamharu nimega „%s“. +editor.cannot_commit_to_protected_branch = Kaitstud alamharusse nimega „%s“ ei saa sissekandeid teha. +commit.revert-content = Vali alamharu, kuhu tahad tagasi pöörata: +issues.delete_branch_at = `kustutatud alamharu %s %s` +pulls.filter_branch = Filtreeri alamharu alusel +pulls.nothing_to_compare_have_tag = Valitud alamharud/sildid on võrdsed. +activity.git_stats_push_to_branch = alamharusse %s ja +activity.git_stats_push_to_all_branches = kõikidesse alamharudesse. +activity.git_stats_on_default_branch = Alamharus %s, +settings.branches.switch_default_branch = Vaheta vaikimisi alamharusse +settings.branch_filter = Alamharude filter +settings.protected_branch = Alamharu kaitse +settings.branch_protection = %s alamharu kaitsmise reeglid +settings.protect_new_rule = Lisa uus alamharu kaitsmise reegel +settings.rename_branch = Muuda alamharu nime +branch.name = Alamharu nimi +branch.already_exists = Alamharu nimega „%s“ on juba olemas. +branch.delete = Kustuta alamharu „%s“ +branch.delete_html = Kustuta alamharu +branch.deletion_success = Alamharu „%s“ on kustutatud. +branch.deletion_failed = Alamharu „%s“ kustutamine ei õnnestunud. +branch.create_branch = Loo Alamharu „%s“ +branch.create_from = allikast „%s“ +branch.create_success = Alamharu „%s“ on loodud. +branch.branch_already_exists = Alamharu nimega „%s“ on selles lähtekoodihoidlas juba olemas. +branch.branch_name_conflict = Alamharu nimi „%s“ on vastolus olemasoleva alamharuga „%s“. +branch.deleted_by = Kustutaja: %s +branch.restore_success = Alamharu „%s“ on taastatud. +branch.restore_failed = Alamharu „%s“ taastamine ei õnnestunud. +branch.protected_deletion_failed = Alamharu „%s“ on kaitstud ja teda ei saa kustutada. +branch.default_deletion_failed = Alamharu „%s“ on vaikimisi alamharu ja teda ei saa kustutada. +branch.restore = Taasta alamharu „%s“ +branch.download = Laadi alla alamharu „%s“ +branch.rename = Muuda alamharu „%s“ nime +branch.included_desc = See alamharu on vaikimisi alamharu osa +branch.included = Sealhulgas +branch.create_new_branch = Loo sellest alamharust uus alamharu: +branch.confirm_create_branch = Loo alamharu +branch.warning_rename_default_branch = Sa muudad vaikimisi alamharu nime. +branch.rename_branch_to = Alamharu „%s“ nimi on muutmisel. +branch.create_branch_operation = Loo alamharu +branch.new_branch = Loo uus alamharu +branch.new_branch_from = Loo uus alamharu siit: „%s“ + [actions] variables = Muutujad variables.deletion = Eemalda muutuja @@ -433,5 +581,40 @@ auths.bind_password = Seo salasõna [explore] users = Kasutajad +repos = Koodihoidlad +organizations = Organisatsioonid +code = Kood + [user] -starred = Tärniga märgitud hoidlad \ No newline at end of file +starred = Tärniga märgitud hoidlad +repositories = Koodihoidlad +followers.title.one = Jälgija +followers.title.few = Jälgijad +following.title.one = Sa jälgid +following.title.few = Sa jälgid +follow = Jälgi +unfollow = Lõpeta jälgimine +code = Kood +projects = Projektid +overview = Ülevaade +block = Blokeeri +unblock = Eemalda blokeering +user_bio = Elulugu + +[home] +my_repos = Koodihoidlad +my_orgs = Organisatsioonid +show_archived = Arhiveeritud +show_private = Privaatne + +[modal] +yes = Jah +no = Ei +confirm = Kinnita +cancel = Katkesta + +[action] +compare_branch = Võrdle + +[packages] +alpine.repository.branches = Alamharud \ No newline at end of file diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index 16c6b0228b..c0b69c258e 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -7,7 +7,7 @@ sign_in=ورود sign_in_or=یا sign_out=خروج sign_up=ثبت نام -link_account=پیوند به حساب +link_account=پیوند به حساب‌کاربری register=ثبت نام version=نسخه powered_by=قدرت از %s diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini index 235ff2ed91..c373c8bbbc 100644 --- a/options/locale/locale_fi-FI.ini +++ b/options/locale/locale_fi-FI.ini @@ -151,7 +151,7 @@ confirm_delete_artifact = Haluatko varmasti poistaa artefaktin "%s"? new_migrate.title = Uusi migraatio test = Testi concept_system_global = Yleisesti pätevä -sign_in_with_provider = Kirjaudu %s-tilillä +sign_in_with_provider = Kirjaudu käyttäen %sia filter.is_fork = Forkit filter.is_mirror = Peilit filter.is_template = Mallipohjat @@ -902,7 +902,7 @@ webauthn_key_loss_warning = Jos menetät turva-avaimesi, menetät pääsyn tilil keep_activity_private.description = Julkinen toimintasi näkyy vain sinulle ja instanssin ylläpitäjille. email_desc = Ensisijaista sähköpostiosoitettasi käytetään ilmoituksiin, salasanan palautukseen ja jos sähköpostiosoite ei ole piilotettu, web-pohjaisiin Git-toimenpiteisiin. tokens_desc = Nämä poletit mahdollistavat pääsyn tilillesi Forgejon rajapintaa vasten. -keep_email_private_popup = Sähköpostiosoitettasi ei näytetä profiilissasi, eikä sitä käytetä oletuksena verkkokäyttöliittymän kautta tehtävissä kommiteissa, kuten tiedostojen lähetyksissä, muokkauksissa ja yhdistämiskommiteissa. Sen sijaan voit käyttää erityistä osoitetta %s kommittien linkittämiseen tiliisi. Tämä vaihtoehto ei vaikuta olemassa oleviin kommitteihin. +keep_email_private_popup = Sähköpostiosoitetta ei näytetä profiilisivulla, eikä sitä käytetä oletuksena verkkokäyttöliittymän kautta tehtävissä kommiteissa, kuten tiedostojen lähetyksissä, muokkauksissa ja yhdistämiskommiteissa. Sen sijaan erityistä osoitetta %s voi käyttää kommittien linkittämiseen käyttäjätiliin. Tämä asetus ei vaikuta olemassa oleviin kommitteihin. added_on = Lisätty %s additional_repo_units_hint = Ehdota tietovaraston lisäyksiköiden käyttöönottoa revoke_oauth2_grant_success = Pääsy mitätöity. @@ -1010,6 +1010,19 @@ principal_state_desc = Tätä prinsipaalia on käytetty viimeisen seitsemän pä regenerate_token_success = Poletti on luotu uudelleen. Sovellukset, jotka käyttivät polettia, eivät enää pääse tilillesi. Kyseiset sovellukset tulee päivittää uudella poletilla. quota.sizes.assets.all = Resurssit +can_not_add_email_activations_pending = Aktivointi odottaa. Odota hetki ja yritä uudelleen muutaman minuutin kuluttua, jos haluat lisätä uuden sähköpostiosoitteen. +gpg_invalid_token_signature = Annettu GPG-avain, allekirjoitus ja poletti eivät täsmää, tai poletti on vanhentunut. +ssh_invalid_token_signature = Annettu SSH-avain, allekirjoitus tai poletti eivät täsmää, tai poletti on vanhentunut. +access_token_desc = Valitut poletin käyttöoikeudet rajoittavat valtuuden vain vastaaville API-reiteille. Lue dokumentaatio saadaksesi lisätietoja. + +oauth2_application_remove_description = OAuth2-sovelluksen poistaminen estää sitä pääsemästä valtuutettuihin käyttäjätileihin tässä instanssissa. Jatketaanko? +oauth2_application_locked = Forgejo esirekisteröi joitain OAuth2-sovelluksia käynnistymisen yhteydessä, jos näin on määritetty kokoonpanon asetuksissa. Odottamattoman toiminnan estämiseksi näitä sovelluksia ei voi muokata tai poistaa. Lisätietoja on saatavilla OAuth2-dokumentaatiossa. +quota.rule.exceeded.helper = Objektien yhteiskoko tälle säännölle on ylittänyt kiintiön. + +regenerate_scratch_token_desc = Jos kadotit palautusavaimesi tai käytit sen jo sisäänkirjautumiseen, voit nollata palautusavaimen tästä. +delete_with_all_comments = Tilisi on nuorempi kuin %s. Aavekommenttien välttämiseksi kaikki ongelma- ja vetopyyntökommentit poistetaan tilin mukana. +quota.sizes.git.lfs = Git LFS + [repo] owner=Omistaja owner_helper=Jotkin organisaatiot eivät välttämättä näy pudotusvalikossa, koska tietovarastojen enimmäismäärää on rajoitettu. @@ -1050,7 +1063,7 @@ desc.private=Yksityinen desc.public=Julkinen desc.template=Mallipohja desc.internal=Sisäinen -desc.archived=Arkistoidut +desc.archived=Arkistoitu template.git_hooks=Git-koukut template.webhooks=Webkoukut @@ -1192,7 +1205,7 @@ issues.new.open_milestone=Avoimet merkkipaalut issues.new.closed_milestone=Suljetut merkkipaalut issues.new.assignees=Käsittelijä issues.new.clear_assignees=Tyhjennä käsittelijä -issues.new.no_assignees=Ei käsittelijää +issues.new.no_assignees=Ei käsittelijöitä issues.choose.open_external_link=Avaa issues.choose.blank=Oletus issues.no_ref=Haaraa/tagia ei määritelty @@ -1263,7 +1276,7 @@ issues.reopen_comment_issue=Kommentoi ja avaa uudelleen issues.create_comment=Kommentoi issues.closed_at=`sulki tämän tukipyynnön %s` issues.reopened_at=`avasi tämän tukipyynnön uudelleen %s` -issues.commit_ref_at=`viittasi tähän tukipyyntöön sitoumuksesta %s` +issues.commit_ref_at=`viittasi tähän ongelmaan kommitista %s` issues.author=Tekijä issues.role.owner=Omistaja issues.role.member=Jäsen @@ -1419,7 +1432,7 @@ activity.closed_issues_count_1=suljettu ongelma activity.closed_issues_count_n=suljettua ongelmaa activity.title.issues_created_by=%s luonut %s activity.closed_issue_label=Suljettu -activity.new_issues_count_1=Uusi ongelma +activity.new_issues_count_1=uusi ongelma activity.new_issues_count_n=uutta ongelmaa activity.new_issue_label=Avoinna activity.unresolved_conv_label=Auki @@ -1822,10 +1835,10 @@ readme_helper = Valitse README-tiedoston mallipohja settings.default_merge_style_desc = Oletusarvoinen yhdistämistyyli wiki.back_to_wiki = Takaisin wikisivulle wiki.delete_page_notice_1 = Wikisivun "%s" poistamista ei voi perua. Jatketaanko? -activity.merged_prs_count_1 = Yhdistetty vetopyyntö -activity.merged_prs_count_n = Yhdistettyä vetopyyntöä -activity.opened_prs_count_1 = Ehdotettu vetopyyntö -activity.opened_prs_count_n = Ehdotettua vetopyyntöä +activity.merged_prs_count_1 = yhdistetty vetopyyntö +activity.merged_prs_count_n = yhdistettyä vetopyyntöä +activity.opened_prs_count_1 = ehdotettu vetopyyntö +activity.opened_prs_count_n = ehdotettua vetopyyntöä activity.title.user_1 = %d käyttäjä activity.title.prs_n = %d vetopyyntöä settings.sourcehut_builds.secrets = Salaisuudet @@ -2139,7 +2152,7 @@ issues.add_label = lisäsi nimilapun %s %s issues.due_date_added = lisäsi eräpäivän %s %s issues.review.add_review_request = pyysi katselmointia käyttäjältä %[1]s %[2]s issues.ref_pull_from = `viittasi tähän vetopyyntöön %[3]s %[1]s` -pulls.commit_ref_at = `viittasi tähän vetopyyntöön sitoumuksesta %s` +pulls.commit_ref_at = `viittasi tähän vetopyyntöön kommitista %s` issues.review.comment = katselmoi %s issues.add_labels = lisäsi nimilaput %s %s issues.review.add_review_requests = pyysi katselmointeja käyttäjiltä %[1]s %[2]s @@ -2322,7 +2335,7 @@ pulls.status_checks_warning = Jotkin tarkistukset raportoivat varoituksia pulls.status_checks_error = Jotkin tarkistukset raportoivat virheitä pulls.reopened_at = `avasi tämän vetopyynnön uudelleen %s` pulls.auto_merge_when_succeed = Yhdistä automaatisesti kun kaikki tarkistukset onnistuvat -signing.wont_sign.error = Tapahtui virhe tarkistettaessa, voiko sitoumus allekirjoittaa. +signing.wont_sign.error = Tapahtui virhe tarkistettaessa, voiko kommitin allekirjoittaa. signing.wont_sign.twofa = Sinulla tulee olla kaksivaiheinen todennus käytössä, jotta kommitit voi allekirjoittaa. pulls.data_broken = Tämä vetopyyntö on rikki johtuen puuttuvasta forkkitiedosta. pulls.files_conflicted = Tämä vetopyyntö sisältää muutoksia, jotka ovat ristiriidassa kohdehaaran kanssa. @@ -2549,6 +2562,45 @@ issues.unlock_error = Ongelmaa, jota ei ole lukittu, ei voi avata lukituksesta. +issues.tracking_already_started = `Olet jo aloittanut ajanseurannan toisessa ongelmassa!` +issues.cancel_tracking_history = `perui ajanseurannan %s` + +summary_card_alt = Tietovaraston %s yhteenvetokortti +migrate_options_lfs_endpoint.placeholder = Jos jätetty tyhjäksi, päätepiste johdetaan kloonaus-URL:stä +broken_message = Tämän tietovaraston taustalla olevaa Git-dataa ei voi lukea. Ota yhteys tämän instanssin ylläpitoon tai poista tietovarasto. +issues.edit.already_changed = Muutosten tallentaminen ongelmaan ei onnistu. Vaikuttaa siltä, että sisältöä on jo muutettu toisen käyttäjän toimesta. Päivitä sivu ja yritä muokata uudelleen välttääksesi muiden tekemien muutosten ylikirjoittamisen +issues.choose.invalid_templates = Virheellisiä mallipohjia löytyi %v +issues.filter_assginee_no_assignee = Ei käsittelijää +issues.action_assignee_no_select = Ei käsittelijää +issues.ref_issue_from = `viittasi tähän ongelmaan %[3]s %[1]s` +issues.due_date_invalid = Eräpäivä on virheellinen tai ajanjakson ulkopuolella. Käytä muotoa "yyyy-mm-dd". +issues.dependency.issue_close_blocked = Sinun täytyy sulkea kaikki tämän ongelman estävät ongelmat, ennen kuin voit sulkea tämän ongelman. +issues.review.pending.tooltip = Tämä kommentti ei ole näkyvissä tällä hetkellä muille käyttäjille. Lähettääksesi odottavat kommentit, valitse "%s" -> "%s/%s/%s" sivun yläosasta. +milestones.deletion_desc = Merkkipaalun poistaminen poistaa sen kaikista siihen liittyvistä ongelmista. Jatketaanko? +activity.title.issues_closed_from = %s sulkenut %s +settings.protected_branch_duplicate_rule_name = Tälle joukolle haaroja on jo olemassa sääntö + +commit.contained_in = Tämä kommitti sisältyy haaraan: +issues.ref_closing_from = `viittasi tähän ongelmaan vetopyynnöstä %[3]s, joka sulkee ongelman, %[1]s` +issues.ref_reopening_from = `viittasi tähän ongelmaan vetopyynnöstä %[3]s, joka avaa ongelman uudelleen, %[1]s` +issues.lock_no_reason = lukitsi ja rajoitti keskustelun avustajille %s +issues.dependency.no_permission_1 = Sinulla ei ole oikeutta lukea %d riippuvuutta +issues.dependency.no_permission_n = Sinulla ei ole oikeutta lukea %d riippuvuutta +pulls.editable = Muokattavissa +settings.wiki_branch_rename_success = Tietovaraston wikin haaranimi on normalisoitu onnistuneesti. +settings.wiki_branch_rename_failure = Tietovaraston wikin haaranimen normalisointi epäonnistui. +release.releases_for = Projektin %s julkaisut +release.tags_for = Projektin %s tagit + +size_format = %[1]s: %[2]s, %[3]s: %[4]s +transfer.accept_desc = Siirrä taholle "%s" +transfer.reject_desc = Peru siirto taholle "%s" +invisible_runes_description = `Tämä tiedosto sisältää näkymättömiä Unicode-merkkejä, joita ihminen ei huomaa, mutta jotka mahdollisesti käsitellään eri tavalla tietokoneen toimesta. Jos olet sitä mieltä, että tämä on tarkoituksellista, voit ohittaa tämän varoituksen. Käytä eskapointipainiketta näyttääksesi ne.` +ambiguous_runes_description = `Tämä tiedosto sisältää Unicode-merkkejä, jotka voi olla virheellisesti yhdistettävissä toisiin merkkeihin. Jos olet sitä mieltä, että tämä on tarkoituksellista, voit ohittaa tämän varoituksen. Käytä eskapointipainiketta näyttääksesi ne.` +escape_control_characters = Eskapoi +unescape_control_characters = Poista eskapointi +diff.file_suppressed = Tiedoston eroavaisuutta ei näytetä, koska se on liian suuri + [graphs] component_loading_info = Tämä saattaa kestää hetken… component_failed_to_load = Odottamaton virhe. @@ -2567,7 +2619,7 @@ repo_updated=Päivitetty %s members=Jäsenet teams=Tiimit lower_members=jäsentä -lower_repositories=tietovarastot +lower_repositories=tietovarastoa create_new_team=Uusi tiimi create_team=Luo tiimi org_desc=Kuvaus @@ -2673,6 +2725,9 @@ settings.change_orgname_redirect_prompt.with_cooldown.few = Vanha organisaation teams.all_repositories_helper = Tiimillä on pääsy kaikkiin tietovarastoihin. Tämän valitseminen lisää kaikki olemassa olevat tietovarastot tiimiin. settings.labels_desc = Lisää nimilappuja, joita voi käyttää tämän organisaation kaikkien tietovarastojen ongelmissa. +teams.general_access_helper = Jäsenten oikeudet päätetään alla olevan käyttöoikeustaulun perusteella. +teams.invite_team_member = Kutsu tiimiin %s + [admin] dashboard=Kojelauta users=Käyttäjätilit @@ -3119,6 +3174,9 @@ auths.force_smtps_helper = SMTPS:ää käytetään aina portissa 465. Aseta täm dashboard.resync_all_sshprincipals = Päivitä ".ssh/authorized_principals"-tiedosto Forgejon SSH-prinsipaaleilla. +auths.verify_group_membership = Vahvista ryhmäjäsenyys LDAP:issa (jätä suodatin tyhjäksi ohittaaksesi) +auths.oauth2_map_group_to_team_removal = Poista käyttäjät synkronoiduista tiimeistä, jos käyttäjä ei kuulu vastaavaan ryhmään. + [action] create_repo=loi tietovaraston %s rename_repo=asetti tietovaraston %[1]s uudeksi nimeksi %[3]s @@ -3473,6 +3531,11 @@ runs.no_workflows.help_write_access = Etkö tiedä, miten aloittaa Forgejo Actio +runs.status_no_select = Kaikki tilat + +workflow.dispatch.trigger_found = Tällä työnkululla on workflow_dispatch-tapahtumaliipaisin. +workflow.dispatch.success = Työnkulun suoritusta pyydettiin onnistuneesti. + [projects] type-1.display_name = Yksittäinen projekti deleted.display_name = Poistettu projekti diff --git a/options/locale/locale_fil.ini b/options/locale/locale_fil.ini index 4ab4ccab8e..051399a472 100644 --- a/options/locale/locale_fil.ini +++ b/options/locale/locale_fil.ini @@ -832,7 +832,7 @@ generate_token_success = Nag-generate na ang iyong bagong token. Kopyahin ito ng delete_token = Burahin access_token_deletion = Burahin ang access token access_token_deletion_desc = Ang pagbura ng isang token ay babawiin ang pag-access sa iyong account para sa mga application gamit ito. Ang gawaing ito ay hindi pwedeng baguhin. Magpatuloy? -repo_and_org_access = Access sa Repositoryo at Organisasyon +repo_and_org_access = Access sa repositoryo at organisasyon permissions_public_only = Publiko lamang permissions_access_all = Lahat (publiko, pribado, at limitado) select_permissions = Pumili ng mga pahintulot @@ -938,8 +938,8 @@ keep_activity_private.description = Makikita mo lang at mga tagapangasiwa ng ins language.description = Mase-save ang wika sa iyong account at gagamitin bilang default pagkatapos mong mag-log in. language.localization_project = Tulungan kaming isalin ang Forgejo sa iyong wika! Matuto pa. user_block_yourself = Hindi mo maaaring harangan ang sarili mo. -change_username_redirect_prompt.with_cooldown.one = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown. -change_username_redirect_prompt.with_cooldown.few = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown. +change_username_redirect_prompt.with_cooldown.one = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng pagprotekta na %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang username sa panahon ng pagprotekta. +change_username_redirect_prompt.with_cooldown.few = Magiging available ang lumang username sa lahat pagkatapos ng panahon ng pagprotekta na %[1]d na araw. Maaari mo pa ring ma-claim muli ang lumang username sa panahon ng pagprotekta. keep_pronouns_private = Ipakita lang ang mga panghalip sa mga naka-authenticate na user keep_pronouns_private.description = Itatago nito ang iyong mga panghalip mula sa mga bisita na hindi naka-log in. quota.applies_to_user = Nag-aapply ang mga sumusunod na panuntunan ng quota sa iyong account @@ -2752,7 +2752,7 @@ dashboard.deleted_branches_cleanup = Linisin ang mga binurang branch dashboard.update_migration_poster_id = I-update ang mga migration poster ID dashboard.git_gc_repos = I-garbage collect ang lahat ng mga repositoryo dashboard.resync_all_sshprincipals = I-update ang ".ssh/authorized_principals" file sa mga principal ng Forgejo SSH. -dashboard.resync_all_hooks = I-resychronize ang mga pre-receive, update at post-receive hook para sa lahat ng mga repositoryo +dashboard.resync_all_hooks = I-resychronize ang mga Git hook ng lahat ng mga repositoryo (pre-receive, post-receive, proc-receive, …) dashboard.cleanup_hook_task_table = Linisin ang hook_task table dashboard.cleanup_packages = Linisin ang mga na-expire na package dashboard.cleanup_actions = Linisin ang mga nag-expire na log at artifact mula sa mga aksyon diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 72a4a14dd1..ebcdeb56cc 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -873,7 +873,7 @@ delete_token=Supprimer access_token_deletion=Supprimer le jeton d'accès access_token_deletion_desc=Supprimer un jeton révoquera l'accès à votre compte pour toutes les applications l'utilisant. Cette action est irréversible. Continuer ? delete_token_success=Ce jeton a été supprimé. Les applications l'utilisant n'ont plus accès à votre compte. -repo_and_org_access=Accès aux Organisations et Dépôts +repo_and_org_access=Accès aux dépôts et organisations permissions_public_only=Publique uniquement permissions_access_all=Tout (public, privé et limité) select_permissions=Sélectionner les autorisations diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index 41a4f51227..7991c98994 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -9,7 +9,7 @@ sign_in_with_provider = Sínigh isteach le %s sign_in_or = nó sign_out = Sínigh amach sign_up = Cláraigh -link_account = Cuntas Nasc +link_account = Nasc cuntas register = Cláraigh version = Leagan powered_by = Cumhachtaithe ag %s @@ -96,9 +96,9 @@ copy_error = Theip ar an gcóipeáil copy_type_unsupported = Ní féidir an cineál comhaid seo a chóipeáil write = Scríobh preview = Réamhamharc -loading = Á lódáil... +loading = Á lódáil… error = Earráid -error404 = Níl an leathanach atá tú ag iarraidh a bhaint amach annníl tú údaraithe chun é a fheiceáil. +error404 = Níl an leathanach atá tú ag iarraidh a bhaint amach ann, nó baineadh éníl údarú agat é a fheiceáil. go_back = Ar ais invalid_data = Sonraí neamhbhailí: %v never = Riamh @@ -125,8 +125,26 @@ filter.not_archived = Gan Cartlannaithe filter.public = Poiblí filter.private = Príobháideach +return_to_forgejo = Fill ar ais go Forgejo +toggle_menu = Roghchlár scoránaigh +new_repo.title = Stórlann nua +new_migrate.title = Imirce nua +new_org.title = Eagraíocht nua +new_repo.link = Stórlann nua +new_migrate.link = Imirce nua +new_org.link = Eagraíocht nua +error413 = Tá do chuóta ídithe agat. +confirm_delete_artifact = An bhfuil tú cinnte gur mian leat an déantán "%s" a scriosadh? +filter.clear = Glan scagairí +filter.is_fork = Forcanna +filter.not_fork = Ní forcanna +filter.is_mirror = Scátháin +filter.not_mirror = Ní scátháin +filter.is_template = Teimpléid +filter.not_template = Ní teimpléid iad + [search] -search = Cuardaigh... +search = Cuardaigh… type_tooltip = Cineál cuardaigh fuzzy = Doiléir fuzzy_tooltip = Cuir san áireamh torthaí a mheaitseálann an téarma cuardaigh go dlúth freisin @@ -148,20 +166,32 @@ issue_kind = Saincheisteanna cuardaigh… pull_kind = Cuardaigh iarratais tarraingthe… keyword_search_unavailable = Níl cuardach de réir eochairfhocal ar fáil faoi láthair. Déan teagmháil le riarthóir an láithreáin. +union = Aontas +union_tooltip = Cuir torthaí san áireamh a mheaitseálann aon cheann de na heochairfhocail scartha le spás bán +regexp = RegExp +regexp_tooltip = Léirmhínigh an téarma cuardaigh mar ghnáthléiriú + [aria] navbar = Barra Nascleanúint footer = Buntásc footer.links = Naisc +footer.software = Maidir leis an mbogearra seo + [heatmap] number_of_contributions_in_the_last_12_months = %s ranníocaíochtaí le 12 mhí anuas less = Níos lú more = Níos mó +contributions_zero = Gan aon ranníocaíochtaí +contributions_format = {contributions} ar {month} {day}, {year} +contributions_one = ranníocaíocht +contributions_few = ranníocaíochtaí + [editor] buttons.heading.tooltip = Cuir ceannteideal leis -buttons.bold.tooltip = Cuir téacs trom leis -buttons.italic.tooltip = Cuir téacs iodálach leis +buttons.bold.tooltip = Cuir téacs trom leis (Ctrl+B / ⌘B) +buttons.italic.tooltip = Cuir téacs iodálach leis (Ctrl+I / ⌘I) buttons.quote.tooltip = Téacs luaigh buttons.code.tooltip = Cuir cód leis buttons.link.tooltip = Cuir nasc leis @@ -174,6 +204,19 @@ buttons.switch_to_legacy.tooltip = Úsáid an eagarthóir oidhreachta ina ionad buttons.enable_monospace_font = Cumasaigh cló monospace buttons.disable_monospace_font = Díchumasaigh cló monospace +buttons.indent.tooltip = Míreanna neadaithe leibhéal amháin +buttons.unindent.tooltip = Díneadaigh míreanna leibhéal amháin +buttons.new_table.tooltip = Cuir tábla leis +table_modal.header = Cuir tábla leis +table_modal.placeholder.header = Ceanntásc +table_modal.placeholder.content = Ábhar +table_modal.label.rows = Sraitheanna +table_modal.label.columns = Colúin +link_modal.header = Cuir nasc leis +link_modal.url = Url +link_modal.description = Cur síos +link_modal.paste_reminder = Leid: Le URL i do ghearrthaisce, is féidir leat é a ghreamú go díreach isteach san eagarthóir chun nasc a chruthú. + [filter] string.asc = A - Z string.desc = Z - A @@ -183,6 +226,9 @@ occurred = Tharla earráid not_found = Ní raibh an sprioc in ann a fháil. network_error = Earráid líonra +report_message = Má chreideann tú gur fabht Forgejo atá ann, déan cuardach ar shaincheisteanna ar Codeberg nó oscail saincheist nua más gá. +server_internal = Earráid inmheánach freastalaí + [startpage] app_desc = Seirbhís Git gan phian, féin-óstáil install = Éasca a shuiteáil @@ -191,6 +237,10 @@ platform = Tras-ardán lightweight = Éadrom license = Foinse Oscailte +platform_desc = Tá sé deimhnithe go n-oibríonn Forgejo ar chórais oibriúcháin saor in aisce ar nós Linux agus FreeBSD, chomh maith le hailtireachtaí LAP éagsúla. Roghnaigh an ceann is fearr leat! +lightweight_desc = Tá riachtanais íosta ísle ag Forgejo agus is féidir é a rith ar Raspberry Pi saor. Sábháil fuinneamh do mheaisín! +license_desc = Téigh agus faigh Forgejo! Bí linn trí cur leis chun an tionscadal seo a dhéanamh níos fearr fós. Ná bíodh drogall ort a bheith i do rannpháirtí! + [install] install = Suiteáil title = Cumraíocht Tosaigh @@ -218,7 +268,7 @@ repo_path = Cosán Fréimhe an Stór repo_path_helper = Sábhálfar stórais iargúlta Git chuig an eolaire seo. lfs_path = Cosán Fréamh Git LFS lfs_path_helper = Stórálfar comhaid a rianóidh Git LFS san eolaire seo. Fág folamh le díchumasú. -domain = Fearann ​​Freastalaí +domain = Fearann freastalaí domain_helper = Seoladh fearainn nó óstach don fhreastalaí. ssh_port = Port Freastalaí SSH app_url_helper = Seoladh bonn le haghaidh URLanna clóin HTTP(S) agus fógraí ríomhphoist. @@ -262,11 +312,52 @@ invalid_log_root_path = Tá an cosán logála neamhbhailí:%v no_reply_address = Fearann Ríomhphoist Folaite password_algorithm = Algartam Hais Pasfhocal invalid_password_algorithm = Algartam hais pasfhocail neamhbhailí -password_algorithm_helper = Socraigh an algartam hashing pasfhocal. Tá riachtanais agus neart éagsúla ag halgartaim. Tá an algartam argon2 sách slán ach úsáideann sé go leor cuimhne agus d'fhéadfadh sé a bheith míchuí do chórais bheaga. +password_algorithm_helper = Socraigh an algartam haiseála pasfhocail. Bíonn riachtanais agus láidreachtaí difriúla ag halgartaim. Tá an algartam argon2 sách slán ach úsáideann sé go leor cuimhne agus d'fhéadfadh sé a bheith mí-oiriúnach do chórais bheaga. enable_update_checker = Cumasaigh Seiceoir Nuashonraithe env_config_keys = Cumraíocht Comhshaoil env_config_keys_prompt = Cuirfear na hathróga comhshaoil seo a leanas i bhfeidhm ar do chomhad cumraíochta freisin: +docker_helper = Má ritheann tú Forgejo taobh istigh de Docker, léigh an doiciméadú le do thoil sula n-athraíonn tú aon socruithe. + +require_db_desc = Éilíonn Forgejo MySQL, PostgreSQL, SQLite3 nó TiDB (prótacal MySQL). +sqlite_helper = Cosán comhaid don bhunachar sonraí SQLite3.
Cuir isteach cosán absalóideach má ritheann tú Forgejo mar sheirbhís. +reinstall_error = Tá tú ag iarraidh suiteáil i mbunachar sonraí Forgejo atá ann cheana féin +reinstall_confirm_message = Is féidir go leor fadhbanna a chruthú má athshuiteáiltear é le bunachar sonraí Forgejo atá ann cheana féin. I bhformhór na gcásanna, ba chóir duit d'"app.ini" atá ann cheana a úsáid chun Forgejo a rith. Má tá a fhios agat cad atá á dhéanamh agat, deimhnigh an méid seo a leanas: +reinstall_confirm_check_3 = Deimhníonn tú go bhfuil tú cinnte go hiomlán go bhfuil an Forgejo seo ag rith leis an suíomh app.ini ceart agus go bhfuil tú cinnte go gcaithfidh tú athshuiteáil a dhéanamh. Deimhníonn tú go n-aithníonn tú na rioscaí thuas. +app_name = Teideal an sampla +app_name_helper = Cuir isteach ainm d’eiseamláire anseo. Taispeánfar é ar gach leathanach. +app_slogan = Slogan samplach +app_slogan_helper = Cuir isteach mana do shampla anseo. Fág folamh chun é a dhíchumasú. +run_user = Úsáideoir le rith mar +run_user_helper = Ainm úsáideora an chórais oibriúcháin a ritheann Forgejo mar úsáid. Tabhair faoi deara go gcaithfidh rochtain a bheith ag an úsáideoir seo ar chonair fréimhe an stórais. +ssh_port_helper = Uimhir an phoirt a úsáidfidh an freastalaí SSH. Fág folamh chun an freastalaí SSH a dhíchumasú. +http_port = Port éisteachta HTTP +http_port_helper = Uimhir an phoirt a úsáidfidh freastalaí gréasáin Forgejo. +app_url = Bun-URL +smtp_from_helper = Seoladh ríomhphoist a úsáidfidh Forgejo. Cuir isteach seoladh ríomhphoist simplí nó bain úsáid as an bhformáid "Ainm" . +offline_mode.description = Díchumasaigh líonraí seachadta ábhair tríú páirtí agus freastalaigh na hacmhainní go léir go háitiúil. +disable_gravatar.description = Díchumasaigh úsáid Gravatar nó foinsí avatar tríú páirtí eile. Úsáidfear íomhánna réamhshocraithe d’avatars úsáideoirí mura n-uaslódálann siad a n-avatar féin chuig an gcás. +federated_avatar_lookup.description = Cuardaigh avatars ag baint úsáide as Libravatar. +disable_registration.description = Ní bheidh ach riarthóirí samplaí in ann cuntais úsáideora nua a chruthú. Moltar go mór clárú a choinneáil díchumasaithe mura bhfuil sé ar intinn agat sampla poiblí a óstáil do gach duine agus má tá tú réidh le déileáil le líon mór cuntas turscair. +allow_only_external_registration = Ceadaigh clárú trí sheirbhísí seachtracha amháin +allow_only_external_registration.description = Ní bheidh úsáideoirí in ann cuntais nua a chruthú ach trí sheirbhísí seachtracha cumraithe a úsáid. +openid_signin.description = Ceadaigh d’úsáideoirí síniú isteach trí OpenID. +openid_signup.description = Ceadaigh d’úsáideoirí cuntais a chruthú trí OpenID má tá féinchlárú cumasaithe. +enable_captcha.description = Éiligh ar úsáideoirí CAPTCHA a úsáid chun cuntais a chruthú. +require_sign_in_view = Éilítear síniú isteach chun ábhar an sampla a fheiceáil +require_sign_in_view.description = Teorainn a chur le rochtain ar ábhar d'úsáideoirí atá sínithe isteach. Ní bheidh aíonna in ann cuairt a thabhairt ach ar na leathanaigh fíordheimhnithe. +default_keep_email_private.description = Cumasaigh seoladh ríomhphoist a cheilt d’úsáideoirí nua de réir réamhshocraithe ionas nach sceithfear an fhaisnéis seo díreach tar éis clárúcháin. +default_allow_create_organization.description = Ceadaigh d’úsáideoirí nua eagraíochtaí a chruthú de réir réamhshocraithe. Nuair a bhíonn an rogha seo díchumasaithe, beidh ar riarthóir cead a thabhairt d’úsáideoirí nua eagraíochtaí a chruthú. +default_enable_timetracking.description = Ceadaigh úsáid ghné rianaithe ama do stórtha nua de réir réamhshocraithe. +admin_setting.description = Is rogha é cuntas riarthóra a chruthú. Beidh an chéad úsáideoir cláraithe ina riarthóir go huathoibríoch. +config_location_hint = Sábhálfar na roghanna cumraíochta seo i: +install_btn_confirm = Suiteáil Forgejo +test_git_failed = Níorbh fhéidir an t-ordú "git" a thástáil: %v +sqlite3_not_available = Ní thacaíonn an leagan seo de Forgejo le SQLite3. Íoslódáil an leagan dénártha oifigiúil ó %s (ní an leagan "gobuild"). +run_user_not_match = Ní hé an t-ainm úsáideora "úsáideoir le rith mar" an t-ainm úsáideora reatha: %s -> %s +enable_update_checker_helper_forgejo = Déanfaidh sé seiceáil tréimhsiúil le haghaidh leaganacha nua de Forgejo trí thaifead DNS TXT a sheiceáil ag release.forgejo.org. +no_reply_address_helper = Ainm fearainn d'úsáideoirí a bhfuil seoladh ríomhphoist i bhfolach acu. Mar shampla, logálfar an t-ainm úsáideora "joe" i Git mar "joe@noreply.example.org" má shocraítear an fearann ríomhphoist i bhfolach go "noreply.example.org". + [home] uname_holder = Ainm Úsáideora nó Seoladh Ríomhphoist switch_dashboard_context = Athraigh Comhthéacs an Deais @@ -285,6 +376,8 @@ show_only_private = Ag taispeáint príobháideach amháin show_only_public = Ag taispeáint poiblí amháin issues.in_your_repos = I do stórais +my_orgs = Eagraíochtaí + [explore] repos = Stórais users = Úsáideoirí @@ -298,7 +391,7 @@ relevant_repositories = Níl ach stórtha ábhartha á dtaispeáint, Sínigh isteach anois! +hint_register = An bhfuil cuntas uait? Cláraigh anois. +sign_up_button = Cláraigh anois. +confirmation_mail_sent_prompt = Tá ríomhphost deimhnithe nua seolta chuig %s. Chun an próiseas clárúcháin a chríochnú, seiceáil do bhosca isteach agus lean an nasc a cuireadh ar fáil laistigh den chéad %s eile. Mura bhfuil an ríomhphost ceart, is féidir leat logáil isteach agus ríomhphost deimhnithe eile a iarraidh chuig seoladh difriúil. +reset_password_mail_sent_prompt = Tá ríomhphost deimhnithe seolta chuig %s. Chun an próiseas aisghabhála cuntais a chríochnú, seiceáil do bhosca isteach agus lean an nasc a chuirtear ar fáil laistigh den chéad %s eile. +prohibit_login = Tá an cuntas ar fionraí +prohibit_login_desc = Tá do chuntas curtha ar fionraí ó idirghníomhú leis an gcás. Téigh i dteagmháil le riarthóir an chás chun rochtain a fháil ar ais. +change_unconfirmed_email_summary = Athraigh an seoladh ríomhphoist a seoltar ríomhphost gníomhachtaithe chuige. +change_unconfirmed_email = Má thug tú an seoladh ríomhphoist mícheart le linn clárúcháin, is féidir leat é a athrú thíos, agus seolfar dearbhú chuig an seoladh nua ina ionad. +change_unconfirmed_email_error = Ní féidir an seoladh ríomhphoist a athrú: %v +send_reset_mail = Seol ríomhphost aisghabhála +non_local_account = Ní féidir le húsáideoirí nach áitiúla iad a bpasfhocal a nuashonrú tríd an gcomhéadan gréasáin Forgejo. +unauthorized_credentials = Tá na dintiúir mícheart nó imithe in éag. Déan iarracht d’ordú a athdhéanamh nó féach %s le haghaidh tuilleadh eolais +use_onetime_code = Úsáid cód aonuaire +oauth_signin_tab = Nasc le cuntas atá ann cheana féin +authorize_application_description = Má dheonaíonn tú rochtain, beidh sé in ann rochtain a fháil ar fhaisnéis do chuntais go léir agus scríobh chuici, lena n-áirítear stórtha príobháideacha agus eagraíochtaí. +sign_in_openid = Lean ar aghaidh le OpenID + [mail] view_it_on = Féach air ar %s reply = nó freagra a thabhairt ar an r-phost seo go díreach @@ -396,6 +507,33 @@ team_invite.text_1 = Tá cuireadh tugtha ag %[1]s duit chun dul le foireann %[2] team_invite.text_2 = Cliceáil ar an nasc seo a leanas le do thoil chun dul isteach san fhoireann: team_invite.text_3 = Nóta: Bhí an cuireadh seo beartaithe do %[1]s. Mura raibh tú ag súil leis an gcuireadh seo, is féidir leat neamhaird a dhéanamh den ríomhphost seo. +link_not_working_do_paste = Nach bhfuil an nasc ag obair? Bain triail as é a chóipeáil agus a ghreamú i mbarra URL do bhrabhsálaí. +admin.new_user.subject = Úsáideoir nua %s díreach cláraithe +admin.new_user.user_info = Faisnéis úsáideora +admin.new_user.text = Le do thoil, cliceáil anseo chun an t-úsáideoir seo a bhainistiú ón bpainéal riaracháin. +register_notify.text_2 = Is féidir leat síniú isteach i do chuntas ag baint úsáide as d'ainm úsáideora: %s +register_notify.text_3 = Más duine eile a chruthaigh an cuntas seo duit, beidh ort do phasfhocal a shocrú ar dtús. +reset_password.text = Más tusa a bhí ann, cliceáil an nasc seo a leanas le do chuntas a aisghabháil laistigh de %s: +password_change.subject = Tá d’fhocal faire athraithe +password_change.text_1 = Athraíodh pasfhocal do chuntais díreach anois. +primary_mail_change.subject = Tá do phríomhphost athraithe +primary_mail_change.text_1 = Athraíodh príomhsheoladh ríomhphoist do chuntais go %[1]s díreach anois. Ciallaíonn sé seo nach bhfaighidh an seoladh ríomhphoist seo fógraí ríomhphoist a thuilleadh chun do chuntas. +totp_disabled.subject = Tá TOTP díchumasaithe +totp_disabled.text_1 = Díchumasaíodh pasfhocal aonuaire bunaithe ar am (TOTP) ar do chuntas díreach anois. +totp_disabled.no_2fa = Níl aon mhodhanna 2FA eile cumraithe a thuilleadh, rud a chiallaíonn nach gá logáil isteach i do chuntas le 2FA a thuilleadh. +removed_security_key.subject = Baineadh eochair slándála +removed_security_key.text_1 = Baineadh an eochair slándála "%[1]s" as do chuntas díreach anois. +removed_security_key.no_2fa = Níl aon mhodhanna 2FA eile cumraithe a thuilleadh, rud a chiallaíonn nach gá logáil isteach i do chuntas le 2FA a thuilleadh. +account_security_caution.text_1 = Más tusa a bhí ann, is féidir leat neamhaird a dhéanamh den ríomhphost seo go sábháilte. +account_security_caution.text_2 = Mura tusa a bhí ann, tá do chuntas i mbaol. Téigh i dteagmháil le riarthóirí an tsuímh seo, le do thoil. +totp_enrolled.subject = Tá TOTP gníomhachtaithe agat mar mhodh 2FA +totp_enrolled.text_1.no_webauthn = Tá TOTP cumasaithe agat chun do chuntas díreach anois. Ciallaíonn sé seo go gcaithfidh tú TOTP a úsáid mar mhodh 2FA i ngach logáil isteach chuig do chuntas amach anseo. +totp_enrolled.text_1.has_webauthn = Tá TOTP cumasaithe agat chun do chuntas díreach anois. Ciallaíonn sé seo, i gcás gach logáil isteach chuig do chuntas amach anseo, gur féidir leat TOTP a úsáid mar mhodh 2FA nó aon cheann de do chuid eochracha slándála a úsáid. +repo.transfer.subject_to = Tá %s ag iarraidh stórlann "%s" a aistriú go %s +repo.transfer.subject_to_you = Tá %s ag iarraidh stórlann "%s" a aistriú chugat +repo.collaborator.added.subject = Chuir %s le %s thú mar chomhoibrí +repo.collaborator.added.text = Cuireadh leis an stór thú mar chomhoibrí: + [modal] yes = Tá no = Níl @@ -423,7 +561,7 @@ require_error = ` ní féidir a bheith folamh.` git_ref_name_error = ` caithfidh gur ainm tagartha Git dea-chruthaithe é.` size_error = ` ní mór méid %s.` min_size_error = ` ní mór go mbeadh carachtar %s ar a laghad ann.` -max_size_error = caithfidh %s carachtar ar a mhéad a bheith ann. +max_size_error = `ní mór %s carachtar ar a mhéad a bheith ann.` email_error = `ní seoladh ríomhphoist bailí é.` url_error = `ní URL bailí é "%s".` include_error = ` ní mór fotheaghrán a bheith ann "%s".` @@ -475,6 +613,29 @@ auth_failed = Theip ar fhíordheimhniú:%v target_branch_not_exist = Níl spriocbhrainse ann. admin_cannot_delete_self = Ní féidir leat tú féin a scriosadh nuair is riarachán tú. Bain do phribhléidí riaracháin ar dtús. +FullName = Ainm iomlán +Description = Cur síos +Pronouns = Forainmneacha +Biography = Beathaisnéis +Website = Suíomh Gréasáin +Location = Suíomh +To = Ainm na brainse +AccessToken = Comhartha rochtana +alpha_dash_error = `Níor cheart ach carachtair alfa-uimhriúla, fleascáin ("-") agus fo-líne ("_") a bheith sa.` +alpha_dash_dot_error = `Níor cheart ach carachtair alfa-uimhriúla, fleasc ("-"), fo-líne ("_") agus ponc (".") a bheith sa.` +username_error = `Ní féidir ach carachtair alfa-uimhriúla ("0-9", "a-z", "A-Z"), fleasc ("-"), fo-líne ("_") agus ponc (".") a bheith ann. Ní féidir é a thosú ná a chríochnú le carachtair neamh-alfa-uimhriúla, agus tá cosc ar charachtair neamh-alfa-uimhriúla as a chéile ach an oiread.` +username_error_no_dots = `Ní féidir ach carachtair alfa-uimhriúla ("0-9", "a-z", "A-Z"), fleasc ("-") agus fo-líne ("_") a bheith ann. Ní féidir é a thosú ná a chríochnú le carachtair neamh-alfa-uimhriúla, agus tá cosc ar charachtair neamh-alfa-uimhriúla as a chéile ach an oiread.` +username_claiming_cooldown = Ní féidir an t-ainm úsáideora a éileamh, mar níl a thréimhse fuaraithe thart fós. Is féidir é a éileamh ar %[1]s. +email_domain_is_not_allowed = Tá coimhlint idir fearann seoladh ríomhphoist an úsáideora %s agus EMAIL_DOMAIN_ALLOWLIST nó EMAIL_DOMAIN_BLOCKLIST. Cinntigh go bhfuil an seoladh ríomhphoist socraithe i gceart agat. +last_org_owner = Ní féidir leat an t-úsáideoir deireanach a bhaint den fhoireann "úinéirí". Ní mór úinéir amháin ar a laghad a bheith ann d'eagraíocht. +unable_verify_ssh_key = Ní féidir an eochair SSH a fhíorú, déan seiceáil dhúbailte uirthi le haghaidh earráidí. +still_own_repo = Tá stór amháin nó níos mó i do chuntas, scrios nó aistrigh iad ar dtús. +still_has_org = Is ball d'eagraíocht amháin nó níos mó do chuntas, fág iad ar dtús. +still_own_packages = Tá pacáiste amháin nó níos mó i do chuntas, scrios iad ar dtús. +org_still_own_repo = Tá stór amháin nó níos mó fós faoi úinéireacht na heagraíochta seo, scrios nó aistrigh iad ar dtús. +org_still_own_packages = Tá pacáiste amháin nó níos mó fós ag an eagraíocht seo, scrios iad ar dtús. +required_prefix = Ní mór an ionchur a thosú le "%s" + [user] change_avatar = Athraigh do abhatár… joined_on = Cláraigh ar %s @@ -495,6 +656,29 @@ disabled_public_activity = Dhíchumasaigh an t-úsáideoir seo infheictheacht ph form.name_reserved = Tá an t-ainm úsáideora "%s" in áirithe. form.name_pattern_not_allowed = Ní cheadaítear an patrún "%s" in ainm úsáideora. +followers.title.one = Leantóir +followers.title.few = Leantóirí +following.title.one = Ag leanúint +following.title.few = Ag leanúint +followers_one = %d leantóir +followers_few = %d leantóirí +following_one = %d ag leanúint +following_few = %d ag leanúint +block_user = Úsáideoir blocáilte +block_user.detail = Tabhair faoi deara go bhfuil éifeachtaí eile ag baint le húsáideoir a bhlocáil, amhail: +block_user.detail_1 = Scoirfidh sibh de bheith ag leanúint a chéile agus ní bheidh sibh in ann leanúint a chéile. +block_user.detail_2 = Ní bheidh an t-úsáideoir seo in ann idirghníomhú leis na stórtha atá i do sheilbh, ná leis na saincheisteanna agus na tuairimí atá cruthaithe agat. +block_user.detail_3 = Ní bheidh sibh in ann a chéile a chur leis mar chomhoibritheoirí stóir. +follow_blocked_user = Ní féidir leat an t-úsáideoir seo a leanúint mar gur chuir tú bac air nó mar gur chuir an t-úsáideoir seo bac ort. +block = Bloc +unblock = Díbhlocáil +public_activity.visibility_hint.self_public = Tá do ghníomhaíocht le feiceáil ag gach duine, seachas idirghníomhaíochtaí i spásanna príobháideacha. Cumraigh. +public_activity.visibility_hint.admin_public = Tá an ghníomhaíocht seo le feiceáil ag gach duine, ach mar riarthóir is féidir leat idirghníomhaíochtaí i spásanna príobháideacha a fheiceáil freisin. +public_activity.visibility_hint.self_private = Ní féidir ach leatsa agus le riarthóirí an cháis do ghníomhaíocht a fheiceáil. Cumraigh. +public_activity.visibility_hint.admin_private = Tá an ghníomhaíocht seo le feiceáil agat mar is riarthóir thú, ach ba mhaith leis an úsáideoir go bhfanfadh sí príobháideach. +public_activity.visibility_hint.self_private_profile = Ní féidir ach leatsa agus le riarthóirí an cháis do ghníomhaíocht a fheiceáil mar go bhfuil do phróifíl príobháideach. Cumraigh. +form.name_chars_not_allowed = Tá carachtair neamhbhailí san ainm úsáideora "%s". + [settings] profile = Próifíl account = Cuntas @@ -521,13 +705,13 @@ update_language_success = Tá an teanga nuashonraithe. update_profile_success = Nuashonraíodh do phróifíl. change_username = Tá d'ainm úsáideora athraithe. change_username_prompt = Nóta: Athraíonn athrú d'ainm úsáideora URL do chuntais freisin. -change_username_redirect_prompt = Athreoróidh an sean-ainm úsáideora go dtí go n-éilíonn duine é +change_username_redirect_prompt = Déanfar an seanainm úsáideora a atreorú go dtí go n-éileoidh duine éigin é. continue = Lean ar aghaidh cancel = Cealaigh language = Teanga ui = Téama hidden_comment_types = Cineálacha tráchtaireachta ceilte -hidden_comment_types.ref_tooltip = Tuairimí ina dtagraíodh an tsaincheist seo ó shaincheiste/coiste eile... +hidden_comment_types.ref_tooltip = Tráchtanna inar tagraíodh don cheist seo ó cheist/tiomantas/… eile hidden_comment_types.issue_ref_tooltip = Tuairimí ina n-athraíonn an t-úsáideoir an brainse/clib a bhaineann leis an tsaincheist comment_type_group_reference = Tagairt comment_type_group_label = Lipéad @@ -559,7 +743,7 @@ new_password = Pasfhocal Nua retype_new_password = Deimhnigh Pasfhocal Nua password_incorrect = Tá an pasfhocal reatha mícheart. manage_emails = Bainistigh Seoltaí Ríomhphoist -email_desc = Úsáidfear do phríomhsheoladh ríomhphoist le haghaidh fógraí, aisghabháil pasfhocal agus, ar choinníoll nach bhfuil sé i bhfolach, oibríochtaí Git bunaithe ar an ngréas +email_desc = Úsáidfear do phríomhsheoladh ríomhphoist le haghaidh fógraí, aisghabháil pasfhocail agus, ar choinníoll nach bhfuil sé i bhfolach, oibríochtaí Git gréasánbhunaithe. primary = Príomhúil activated = Gníomhachtaithe requires_activation = Éilíonn gníomhachtú @@ -569,7 +753,7 @@ activations_pending = Gníomhartha ar Feitheamh can_not_add_email_activations_pending = Tá gníomhachtú ar feitheamh, déan iarracht arís i gceann cúpla nóiméad más mian leat ríomhphost nua a chur leis. delete_email = Bain email_deletion = Bain Seoladh R-phoist -email_deletion_desc = Bainfear an seoladh ríomhphoist agus an fhaisnéis ghaolmhar as do chuntas. Ní bheidh na tiomáintí Git a bhaineann leis an seoladh ríomhphoist seo athraithe. Lean ar aghaidh? +email_deletion_desc = Bainfear an seoladh ríomhphoist seo agus faisnéis ghaolmhar as do chuntas. Fanfaidh na gealltanais Git ón seoladh ríomhphoist seo gan athrú. Ar mhaith leat leanúint ar aghaidh? email_deletion_success = Tá an seoladh ríomhphoist bainte. theme_update_success = Nuashonraíodh do théama. theme_update_error = Níl an téama roghnaithe ann. @@ -651,12 +835,12 @@ generate_new_token = Gin Comhartha Nua token_name = Ainm Comhartha generate_token = Gin Comhartha generate_token_success = Gintear do chomhartha nua. Cóipeáil é anois mar ní thaispeánfar é arís. -generate_token_name_duplicate = Úsáideadh %s mar ainm feidhmchláir cheana féin. Úsáid ceann nua le do thoil. +generate_token_name_duplicate = Tá %s in úsáid mar ainm feidhmchláir cheana féin. Bain úsáid as ceann nua le do thoil. delete_token = Scrios access_token_deletion = Scrios Comhartha Rochtana access_token_deletion_desc = Cúlghairfear rochtain ar do chuntas le haghaidh feidhmchláir a úsáideann é a scriosadh comhartha. Ní féidir é seo a chur ar ais. Lean ar aghaidh? delete_token_success = Tá an comhartha scriosta. Níl rochtain ag iarratais a úsáideann é ar do chuntas a thuilleadh. -repo_and_org_access = Rochtain Stórála agus Eagraíochta +repo_and_org_access = Rochtain ar stórtha agus ar eagraíochta permissions_public_only = Poiblí amháin permissions_access_all = Gach (poiblí, príobháideach agus teoranta) select_permissions = Roghnaigh ceadanna @@ -709,7 +893,7 @@ then_enter_passcode = Agus cuir isteach an paschód a léirítear san fheidhmchl passcode_invalid = Tá an pascód mícheart. Bain triail as arís. twofa_enrolled = Tá do chuntas cláraithe go rathúil. Stóráil d'eochair aisghabhála aonúsáide (%s) in áit shábháilte, mar ní thaispeánfar é arís. twofa_failed_get_secret = Theip ar rún a fháil. -webauthn_desc = Is feistí crua-earraí iad eochracha slándála ina bhfuil eochracha cripte Is féidir iad a úsáid le haghaidh fíordheimhniú dhá fhachtóir. Caithfidh eochracha slándála tacú le caigh deán Fíordheimhnithe WebAuthn +webauthn_desc = Is gléasanna crua-earraí iad eochracha slándála ina bhfuil eochracha cripteagrafacha. Is féidir iad a úsáid le haghaidh fíordheimhniú dhá fhachtóir. Ní mór d'eochracha slándála tacú leis an gcaighdeán WebAuthn Authenticator. webauthn_register_key = Cuir Eochair Slándála webauthn_nickname = Leasainm webauthn_delete_key = Bain Eochair Slándála @@ -740,6 +924,89 @@ visibility.limited = Teoranta visibility.private = Príobháideach visibility.private_tooltip = Ní fheictear ach do bhaill d'eagraíochtaí a chuaigh tú isteach +orgs = Eagraíochtaí +blocked_users = Úsáideoirí blocáilte +storage_overview = Forbhreathnú ar stóráil +quota = Cuóta +biography_placeholder = Inis beagán do dhaoine eile fút féin! (Tacaítear le Markdown) +profile_desc = Fút féin +password_username_disabled = Ní cheadaítear d’úsáideoirí nach úsáideoirí áitiúla iad a n-ainm úsáideora a athrú. Téigh i dteagmháil le riarthóir do shuíomh le haghaidh tuilleadh sonraí. +pronouns = Forainmneacha +pronouns_unspecified = Gan sonrú +update_theme = Athraigh téama +update_language = Athraigh teanga +change_username_redirect_prompt.with_cooldown.one = Beidh an seanainm úsáideora ar fáil do gach duine tar éis tréimhse fuaraithe %[1]d lá. Is féidir leat an seanainm úsáideora a éileamh ar ais fós le linn na tréimhse fuaraithe. +change_username_redirect_prompt.with_cooldown.few = Beidh an seanainm úsáideora ar fáil do gach duine tar éis tréimhse fuaraithe %[1]d lá. Is féidir leat an seanainm úsáideora a éileamh ar ais fós le linn na tréimhse fuaraithe. +language.title = Teanga réamhshocraithe +language.description = Sábhálfar an teanga seo chuig do chuntas agus úsáidfear í mar an teanga réamhshocraithe tar éis duit logáil isteach. +language.localization_project = Cabhraigh linn Forgejo a aistriú go do theanga féin! Foghlaim tuilleadh. +hints = Leideanna +additional_repo_units_hint = Moltar aonaid stórtha breise a chumasú +additional_repo_units_hint_description = Taispeáin leid "Cumasaigh níos mó" do stórtha nach bhfuil na haonaid uile atá ar fáil cumasaithe iontu. +update_hints = Leideanna nuashonraithe +update_hints_success = Tá na leideanna nuashonraithe. +hidden_comment_types_description = Ní thaispeánfar cineálacha tráchta atá seiceáilte anseo laistigh de leathanaigh eagráin. Má sheiceálann tú "Lipéad", mar shampla, baintear na tráchtanna uile a dúirt " chuir