diff --git a/.deadcode-out b/.deadcode-out index f9bee43043..61c5bcb055 100644 --- a/.deadcode-out +++ b/.deadcode-out @@ -27,13 +27,15 @@ forgejo.org/models/db TruncateBeans InTransaction DumpTables - GetTableNames forgejo.org/models/dbfs file.renameTo Create Rename +forgejo.org/models/forgefed + GetFederationHost + forgejo.org/models/forgejo/semver GetVersion SetVersionString @@ -65,6 +67,7 @@ forgejo.org/models/user DeleteUserSetting GetFederatedUser GetFederatedUserByUserID + UpdateFederatedUser GetFollowersForUser AddFollower RemoveFollower @@ -245,9 +248,6 @@ forgejo.org/routers/web/org forgejo.org/services/context GetPrivateContext -forgejo.org/services/federation - Init - forgejo.org/services/repository IsErrForkAlreadyExist diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3f250e5682..28fa9e4555 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,7 +6,7 @@ "ghcr.io/devcontainers/features/node:1": { "version": "22" }, - "ghcr.io/devcontainers/features/git-lfs:1.2.5": {}, + "ghcr.io/devcontainers/features/git-lfs:1.2.4": {}, "ghcr.io/warrenbuckley/codespace-features/sqlite:1": {} }, "customizations": { diff --git a/.forgejo/workflows-composite/install-minimum-git-version/action.yaml b/.forgejo/workflows-composite/install-minimum-git-version/action.yaml deleted file mode 100644 index d4e6e3f2a7..0000000000 --- a/.forgejo/workflows-composite/install-minimum-git-version/action.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# -# Install the minimal version of Git supported by Forgejo -# -runs: - using: "composite" - steps: - - name: install git and git-lfs - run: | - set -x - - export DEBIAN_FRONTEND=noninteractive - - 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.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 - - apt-get -q install --allow-downgrades -y -qq /tmp/git-man.deb - apt-get -q install --allow-downgrades -y -qq /tmp/git.deb - apt-get -q install --allow-downgrades -y -qq /tmp/git-lfs.deb diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml index 729cba3723..5aa6c8cd98 100644 --- a/.forgejo/workflows/renovate.yml +++ b/.forgejo/workflows/renovate.yml @@ -28,7 +28,7 @@ jobs: runs-on: docker container: - image: data.forgejo.org/renovate/renovate:41.17.2 + image: data.forgejo.org/renovate/renovate:41.1.4 steps: - name: Load renovate repo cache diff --git a/.forgejo/workflows/testing-integration.yml b/.forgejo/workflows/testing-integration.yml index 102a2d9774..9e5cfb92ed 100644 --- a/.forgejo/workflows/testing-integration.yml +++ b/.forgejo/workflows/testing-integration.yml @@ -33,8 +33,11 @@ jobs: steps: - uses: https://data.forgejo.org/actions/checkout@v4 - uses: ./.forgejo/workflows-composite/setup-env - - name: install git 2.34.1 and git-lfs 3.0.2 - uses: ./.forgejo/workflows-composite/install-minimum-git-version + - name: install git 2.30 + uses: ./.forgejo/workflows-composite/apt-install-from + with: + packages: git/bullseye git-lfs/bullseye + release: bullseye - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-backend test-check' @@ -52,8 +55,11 @@ jobs: steps: - uses: https://data.forgejo.org/actions/checkout@v4 - uses: ./.forgejo/workflows-composite/setup-env - - name: install git 2.34.1 and git-lfs 3.0.2 - uses: ./.forgejo/workflows-composite/install-minimum-git-version + - name: install git 2.30 + uses: ./.forgejo/workflows-composite/apt-install-from + with: + packages: git/bullseye git-lfs/bullseye + release: bullseye - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-sqlite-migration test-sqlite' diff --git a/Makefile b/Makefile index db4ec2fbd5..e770f2a989 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasour GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.34.0 # renovate: datasource=go GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.2 # renovate: datasource=go -RENOVATE_NPM_PACKAGE ?= renovate@41.17.2 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate +RENOVATE_NPM_PACKAGE ?= renovate@41.1.4 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate # https://github.com/disposable-email-domains/disposable-email-domains/commits/main/ DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ... diff --git a/assets/go-licenses.json b/assets/go-licenses.json index c3b261320c..fb6c201a5e 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -595,8 +595,8 @@ "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2015 Huan Du\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/inbucket/html2text", - "path": "github.com/inbucket/html2text/LICENSE", + "name": "github.com/jaytaylor/html2text", + "path": "github.com/jaytaylor/html2text/LICENSE", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2015 Jay Taylor\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" }, { @@ -779,16 +779,6 @@ "path": "github.com/nwaples/rardecode/LICENSE", "licenseText": "Copyright (c) 2015, Nicholas Waples\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" }, - { - "name": "github.com/olekukonko/errors", - "path": "github.com/olekukonko/errors/LICENSE", - "licenseText": "MIT License\n\nCopyright (c) 2025 Oleku Konko\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/olekukonko/ll", - "path": "github.com/olekukonko/ll/LICENSE", - "licenseText": "MIT License\n\nCopyright (c) 2025 Oleku Konko\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/olekukonko/tablewriter", "path": "github.com/olekukonko/tablewriter/LICENSE.md", diff --git a/cmd/dump_repo.go b/cmd/dump_repo.go index 7159d55e99..eb89273e7f 100644 --- a/cmd/dump_repo.go +++ b/cmd/dump_repo.go @@ -82,11 +82,6 @@ wiki, issues, labels, releases, release_assets, milestones, pull_requests, comme } func runDumpRepository(stdCtx context.Context, ctx *cli.Command) error { - setupConsoleLogger(log.INFO, log.CanColorStderr, os.Stderr) - - // setting.DisableLoggerInit() - setting.LoadSettings() // cannot access skip_tls_verify settings otherwise - stdCtx, cancel := installSignals(stdCtx) defer cancel() diff --git a/cmd/hook.go b/cmd/hook.go index 7378dc21ad..909cdfdf84 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -231,6 +231,8 @@ Forgejo or set your environment appropriately.`, "") } } + supportProcReceive := git.CheckGitVersionAtLeast("2.29") == nil + for scanner.Scan() { // TODO: support news feeds for wiki if isWiki { @@ -248,25 +250,31 @@ Forgejo or set your environment appropriately.`, "") total++ lastline++ - // All references should be checked because permission check was delayed. - oldCommitIDs[count] = oldCommitID - newCommitIDs[count] = newCommitID - refFullNames[count] = refFullName - count++ - fmt.Fprint(out, "*") + // If the ref is a branch or tag, check if it's protected + // if supportProcReceive all ref should be checked because + // permission check was delayed + if supportProcReceive || refFullName.IsBranch() || refFullName.IsTag() { + oldCommitIDs[count] = oldCommitID + newCommitIDs[count] = newCommitID + refFullNames[count] = refFullName + count++ + fmt.Fprint(out, "*") - if count >= hookBatchSize { - fmt.Fprintf(out, " Checking %d references\n", count) + if count >= hookBatchSize { + fmt.Fprintf(out, " Checking %d references\n", count) - hookOptions.OldCommitIDs = oldCommitIDs - hookOptions.NewCommitIDs = newCommitIDs - hookOptions.RefFullNames = refFullNames - extra := private.HookPreReceive(ctx, username, reponame, hookOptions) - if extra.HasError() { - return fail(ctx, extra.UserMsg, "HookPreReceive(batch) failed: %v", extra.Error) + hookOptions.OldCommitIDs = oldCommitIDs + hookOptions.NewCommitIDs = newCommitIDs + hookOptions.RefFullNames = refFullNames + extra := private.HookPreReceive(ctx, username, reponame, hookOptions) + if extra.HasError() { + return fail(ctx, extra.UserMsg, "HookPreReceive(batch) failed: %v", extra.Error) + } + count = 0 + lastline = 0 } - count = 0 - lastline = 0 + } else { + fmt.Fprint(out, ".") } if lastline >= hookBatchSize { fmt.Fprint(out, "\n") @@ -505,6 +513,10 @@ Forgejo or set your environment appropriately.`, "") return nil } + if git.CheckGitVersionAtLeast("2.29") != nil { + return fail(ctx, "No proc-receive support", "current git version doesn't support proc-receive.") + } + reader := bufio.NewReader(os.Stdin) repoUser := os.Getenv(repo_module.EnvRepoUsername) repoName := os.Getenv(repo_module.EnvRepoName) diff --git a/cmd/manager_logging.go b/cmd/manager_logging.go index c18bfa919b..c543afe872 100644 --- a/cmd/manager_logging.go +++ b/cmd/manager_logging.go @@ -44,11 +44,6 @@ func defaultLoggingFlags() []cli.Flag { Aliases: []string{"e"}, Usage: "Matching expression for the logger", }, - &cli.StringFlag{ - Name: "exclusion", - Aliases: []string{"x"}, - Usage: "Exclusion for the logger", - }, &cli.StringFlag{ Name: "prefix", Aliases: []string{"p"}, @@ -291,9 +286,6 @@ func commonAddLogger(ctx context.Context, c *cli.Command, mode string, vals map[ if len(c.String("expression")) > 0 { vals["expression"] = c.String("expression") } - if len(c.String("exclusion")) > 0 { - vals["exclusion"] = c.String("exclusion") - } if len(c.String("prefix")) > 0 { vals["prefix"] = c.String("prefix") } diff --git a/cmd/serv.go b/cmd/serv.go index b0571a276c..1fac2d13f5 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -193,10 +193,12 @@ func runServ(ctx context.Context, c *cli.Command) error { } if len(words) < 2 { - // for AGit Flow - if cmd == "ssh_info" { - fmt.Print(`{"type":"agit","version":1}`) - return nil + if git.CheckGitVersionAtLeast("2.29") == nil { + // for AGit Flow + if cmd == "ssh_info" { + fmt.Print(`{"type":"agit","version":1}`) + return nil + } } return fail(ctx, "Too few arguments", "Too few arguments in cmd: %s", cmd) } diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 37d67df5f0..1b8d4c6697 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -631,7 +631,6 @@ LEVEL = Info ;LEVEL= ;FLAGS = stdflags or journald ;EXPRESSION = -;EXCLUSION = ;PREFIX = ;COLORIZE = false ;; diff --git a/go.mod b/go.mod index de6331722b..bb2be827eb 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/ProtonMail/go-crypto v1.3.0 github.com/PuerkitoBio/goquery v1.10.3 github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2 - github.com/alecthomas/chroma/v2 v2.19.0 + github.com/alecthomas/chroma/v2 v2.18.0 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb github.com/blevesearch/bleve/v2 v2.5.2 github.com/buildkite/terminal-to-html/v3 v3.16.8 @@ -42,7 +42,7 @@ require ( github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 github.com/go-chi/chi/v5 v5.2.2 - github.com/go-chi/cors v1.2.2 + github.com/go-chi/cors v1.2.1 github.com/go-co-op/gocron v1.37.0 github.com/go-enry/go-enry/v2 v2.9.2 github.com/go-git/go-git/v5 v5.13.2 @@ -56,15 +56,15 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.2 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/google/go-github/v64 v64.0.0 - github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 + github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e github.com/google/uuid v1.6.0 github.com/gorilla/feeds v1.2.0 github.com/gorilla/sessions v1.4.0 github.com/hashicorp/go-version v1.7.0 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/jhillyerd/enmime/v2 v2.2.0 + github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 + github.com/jhillyerd/enmime/v2 v2.1.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.0 @@ -79,7 +79,7 @@ require ( github.com/minio/minio-go/v7 v7.0.94 github.com/msteinert/pam/v2 v2.1.0 github.com/nektos/act v0.2.52 - github.com/niklasfasching/go-org v1.9.0 + github.com/niklasfasching/go-org v1.8.0 github.com/olivere/elastic/v7 v7.0.32 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.1 @@ -158,7 +158,7 @@ require ( github.com/dlclark/regexp2 v1.11.5 // 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/fatih/color v1.16.0 // indirect github.com/fxamacker/cbor/v2 v2.8.0 // indirect github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect @@ -192,7 +192,7 @@ require ( github.com/libdns/libdns v1.0.0-beta.1 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/markbates/going v1.0.3 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mholt/acmez/v3 v3.1.2 // indirect github.com/miekg/dns v1.1.63 // indirect @@ -205,9 +205,7 @@ require ( github.com/mschoch/smat v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nwaples/rardecode v1.1.3 // indirect - github.com/olekukonko/errors v1.1.0 // indirect - github.com/olekukonko/ll v0.0.9 // indirect - github.com/olekukonko/tablewriter v1.0.7 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect diff --git a/go.sum b/go.sum index 38a9dd5708..639880e2ce 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2/go.mod h1:JitQWJ8JuV4Y github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= -github.com/alecthomas/chroma/v2 v2.19.0 h1:Im+SLRgT8maArxv81mULDWN8oKxkzboH07CHesxElq4= -github.com/alecthomas/chroma/v2 v2.19.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.18.0 h1:6h53Q4hW83SuF+jcsp7CVhLsMozzvQvO8HBbKQW+gn4= +github.com/alecthomas/chroma/v2 v2.18.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= @@ -192,8 +192,8 @@ github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTe 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/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= @@ -215,8 +215,8 @@ github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkPro github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= -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-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= +github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= github.com/go-enry/go-enry/v2 v2.9.2 h1:giOQAtCgBX08kosrX818DCQJTCNtKwoPBGu0qb6nKTY= @@ -307,8 +307,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ= -github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -341,12 +341,12 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/inbucket/html2text v0.9.0 h1:ULJmVcBEMAcmLE+/rN815KG1Fx6+a4HhbUxiDiN+qks= -github.com/inbucket/html2text v0.9.0/go.mod h1:QDaumzl+/OzlSVbNohhmg+yAy5pKjUjzCKW2BMvztKE= +github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA= +github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jhillyerd/enmime/v2 v2.2.0 h1:Pe35MB96eZK5Q0XjlvPftOgWypQpd1gcbfJKAt7rsB8= -github.com/jhillyerd/enmime/v2 v2.2.0/go.mod h1:SOBXlCemjhiV2DvHhAKnJiWrtJGS/Ffuw4Iy7NjBTaI= +github.com/jhillyerd/enmime/v2 v2.1.0 h1:c8Qwi5Xq5EdtMN6byQWoZ/8I2RMTo6OJ7Xay+s1oPO0= +github.com/jhillyerd/enmime/v2 v2.1.0/go.mod h1:EJ74dcRbBcqHSP2TBu08XRoy6y3Yx0cevwb1YkGMEmQ= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -389,10 +389,12 @@ github.com/markbates/going v1.0.3 h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE github.com/markbates/going v1.0.3/go.mod h1:fQiT6v6yQar9UD6bd/D4Z5Afbk9J6BBVBtLiyY4gp2o= github.com/markbates/goth v1.80.0 h1:NnvatczZDzOs1hn9Ug+dVYf2Viwwkp/ZDX5K+GLjan8= github.com/markbates/goth v1.80.0/go.mod h1:4/GYHo+W6NWisrMPZnq0Yr2Q70UntNLn7KXEFhrIdAY= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= @@ -426,20 +428,16 @@ 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/niklasfasching/go-org v1.9.0 h1:4/Sr68Qx06hjC9MVDB/4etGP67JionLHGscLMOClpnk= -github.com/niklasfasching/go-org v1.9.0/go.mod h1:ZAGFFkWvUQcpazmi/8nHqwvARpr1xpb+Es67oUGX/48= +github.com/niklasfasching/go-org v1.8.0 h1:WyGLaajLLp8JbQzkmapZ1y0MOzKuKV47HkZRloi+HGY= +github.com/niklasfasching/go-org v1.8.0/go.mod h1:e2A9zJs7cdONrEGs3gvxCcaAEpwwPNPG7csDpXckMNg= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= -github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= -github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= -github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= -github.com/olekukonko/tablewriter v1.0.7 h1:HCC2e3MM+2g72M81ZcJU11uciw6z/p82aEnm4/ySDGw= -github.com/olekukonko/tablewriter v1.0.7/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E= github.com/olivere/elastic/v7 v7.0.32/go.mod h1:c7PVmLe3Fxq77PIfY/bZmxY/TAamBhCzZ8xDOE09a9k= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -647,6 +645,7 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/models/actions/run.go b/models/actions/run.go index 69592120e9..55def805ed 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -284,10 +284,16 @@ func GetLatestRun(ctx context.Context, repoID int64) (*ActionRun, error) { return &run, nil } -func GetRunBefore(ctx context.Context, _ *ActionRun) (*ActionRun, error) { - // TODO return the most recent run related to the run given in argument - // see https://codeberg.org/forgejo/user-research/issues/63 for context - return nil, nil +// GetRunBefore returns the last run that completed a given timestamp (not inclusive). +func GetRunBefore(ctx context.Context, repoID int64, timestamp timeutil.TimeStamp) (*ActionRun, error) { + var run ActionRun + has, err := db.GetEngine(ctx).Where("repo_id=? AND stopped IS NOT NULL AND stopped v34 NewMigration("Add `notify-email` column to `action_run` table", AddNotifyEmailToActionRun), // v34 -> v35 - NewMigration("Noop because of https://codeberg.org/forgejo/forgejo/issues/8373", NoopAddIndexToActionRunStopped), + NewMigration("Add index to `stopped` column in `action_run` table", AddIndexToActionRunStopped), } // GetCurrentDBVersion returns the current Forgejo database version. diff --git a/models/forgejo_migrations/v35.go b/models/forgejo_migrations/v35.go index ca412d7951..0fb3b43e2c 100644 --- a/models/forgejo_migrations/v35.go +++ b/models/forgejo_migrations/v35.go @@ -4,10 +4,16 @@ package forgejo_migrations //nolint:revive import ( + "forgejo.org/modules/timeutil" + "xorm.io/xorm" ) -// see https://codeberg.org/forgejo/forgejo/issues/8373 -func NoopAddIndexToActionRunStopped(x *xorm.Engine) error { - return nil +func AddIndexToActionRunStopped(x *xorm.Engine) error { + type ActionRun struct { + ID int64 + Stopped timeutil.TimeStamp `xorm:"index"` + } + + return x.Sync(&ActionRun{}) } diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go index 9b502d1c91..7285e347b4 100644 --- a/models/issues/comment_list.go +++ b/models/issues/comment_list.go @@ -101,7 +101,7 @@ func (comments CommentList) loadMilestones(ctx context.Context) error { return nil } - milestones := make(map[int64]*Milestone, len(milestoneIDs)) + milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs)) left := len(milestoneIDs) for left > 0 { limit := db.DefaultMaxInSize @@ -110,7 +110,7 @@ func (comments CommentList) loadMilestones(ctx context.Context) error { } err := db.GetEngine(ctx). In("id", milestoneIDs[:limit]). - Find(&milestones) + Find(&milestoneMaps) if err != nil { return err } @@ -118,8 +118,8 @@ func (comments CommentList) loadMilestones(ctx context.Context) error { milestoneIDs = milestoneIDs[limit:] } - for _, comment := range comments { - comment.Milestone = milestones[comment.MilestoneID] + for _, issue := range comments { + issue.Milestone = milestoneMaps[issue.MilestoneID] } return nil } @@ -140,7 +140,7 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error { return nil } - milestones := make(map[int64]*Milestone, len(milestoneIDs)) + milestoneMaps := make(map[int64]*Milestone, len(milestoneIDs)) left := len(milestoneIDs) for left > 0 { limit := db.DefaultMaxInSize @@ -149,7 +149,7 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error { } err := db.GetEngine(ctx). In("id", milestoneIDs[:limit]). - Find(&milestones) + Find(&milestoneMaps) if err != nil { return err } @@ -157,8 +157,8 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error { milestoneIDs = milestoneIDs[limit:] } - for _, comment := range comments { - comment.OldMilestone = milestones[comment.OldMilestoneID] + for _, issue := range comments { + issue.OldMilestone = milestoneMaps[issue.MilestoneID] } return nil } diff --git a/models/issues/issue_search.go b/models/issues/issue_search.go index 529f0c15d4..91a69c26a7 100644 --- a/models/issues/issue_search.go +++ b/models/issues/issue_search.go @@ -48,9 +48,7 @@ type IssuesOptions struct { //nolint UpdatedBeforeUnix int64 // prioritize issues from this repo PriorityRepoID int64 - // if this issue index (not ID) exists and matches the filters, *and* priorityrepo sort is used, show it first - PriorityIssueIndex int64 - IsArchived optional.Option[bool] + IsArchived optional.Option[bool] // If combined with AllPublic, then private as well as public issues // that matches the criteria will be returned, if AllPublic is false @@ -62,7 +60,7 @@ type IssuesOptions struct { //nolint // applySorts sort an issues-related session based on the provided // sortType string -func applySorts(sess *xorm.Session, sortType string, priorityRepoID, priorityIssueIndex int64) { +func applySorts(sess *xorm.Session, sortType string, priorityRepoID int64) { switch sortType { case "oldest": sess.Asc("issue.created_unix").Asc("issue.id") @@ -99,11 +97,8 @@ func applySorts(sess *xorm.Session, sortType string, priorityRepoID, priorityIss case "priorityrepo": sess.OrderBy("CASE "+ "WHEN issue.repo_id = ? THEN 1 "+ - "ELSE 2 END ASC", priorityRepoID) - if priorityIssueIndex != 0 { - sess.OrderBy("issue.index = ? DESC", priorityIssueIndex) - } - sess.Desc("issue.created_unix"). + "ELSE 2 END ASC", priorityRepoID). + Desc("issue.created_unix"). Desc("issue.id") case "project-column-sorting": sess.Asc("project_issue.sorting").Desc("issue.created_unix").Desc("issue.id") @@ -475,7 +470,7 @@ func Issues(ctx context.Context, opts *IssuesOptions) (IssueList, error) { Join("INNER", "repository", "`issue`.repo_id = `repository`.id") applyLimit(sess, opts) applyConditions(sess, opts) - applySorts(sess, opts.SortType, opts.PriorityRepoID, opts.PriorityIssueIndex) + applySorts(sess, opts.SortType, opts.PriorityRepoID) issues := IssueList{} if err := sess.Find(&issues); err != nil { @@ -499,7 +494,7 @@ func IssueIDs(ctx context.Context, opts *IssuesOptions, otherConds ...builder.Co } applyLimit(sess, opts) - applySorts(sess, opts.SortType, opts.PriorityRepoID, opts.PriorityIssueIndex) + applySorts(sess, opts.SortType, opts.PriorityRepoID) var res []int64 total, err := sess.Select("`issue`.id").Table(&Issue{}).FindAndCount(&res) diff --git a/models/issues/pull_list.go b/models/issues/pull_list.go index ddb813cf44..8fc0491026 100644 --- a/models/issues/pull_list.go +++ b/models/issues/pull_list.go @@ -149,7 +149,7 @@ func PullRequests(ctx context.Context, baseRepoID int64, opts *PullRequestsOptio } findSession := listPullRequestStatement(ctx, baseRepoID, opts) - applySorts(findSession, opts.SortType, 0, 0) + applySorts(findSession, opts.SortType, 0) findSession = db.SetSessionPagination(findSession, opts) prs := make([]*PullRequest, 0, opts.PageSize) found := findSession.Find(&prs) diff --git a/models/migrations/test/tests.go b/models/migrations/test/tests.go index 6be3b3c2fc..c1f0caf19b 100644 --- a/models/migrations/test/tests.go +++ b/models/migrations/test/tests.go @@ -95,8 +95,7 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, fu t.Logf("initializing fixtures from: %s", fixturesDir) if err := unittest.InitFixtures( unittest.FixturesOptions{ - Dir: fixturesDir, - SkipCleanRegistedModels: true, + Dir: fixturesDir, }, x); err != nil { t.Errorf("error whilst initializing fixtures from %s: %v", fixturesDir, err) return x, deferFn diff --git a/models/moderation/abuse_report.go b/models/moderation/abuse_report.go index 3a6244ef4c..dadd61a95e 100644 --- a/models/moderation/abuse_report.go +++ b/models/moderation/abuse_report.go @@ -100,7 +100,7 @@ type AbuseReport struct { // The abuse category selected by the reporter. Category AbuseCategoryType `xorm:"INDEX NOT NULL"` // Remarks provided by the reporter. - Remarks string `xorm:"VARCHAR(500)"` + Remarks string // The ID of the corresponding shadow-copied content when exists; otherwise null. ShadowCopyID sql.NullInt64 `xorm:"DEFAULT NULL"` CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"` diff --git a/models/moderation/shadow_copy.go b/models/moderation/shadow_copy.go index d363610a48..cdd8f69c52 100644 --- a/models/moderation/shadow_copy.go +++ b/models/moderation/shadow_copy.go @@ -17,7 +17,7 @@ import ( type AbuseReportShadowCopy struct { ID int64 `xorm:"pk autoincr"` - RawValue string `xorm:"LONGTEXT NOT NULL"` // A JSON with relevant fields from user, repository, issue or comment table. + RawValue string `xorm:"NOT NULL"` CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"` } diff --git a/models/unittest/fixture_loader.go b/models/unittest/fixture_loader.go index dda5c48d35..67ef1b28df 100644 --- a/models/unittest/fixture_loader.go +++ b/models/unittest/fixture_loader.go @@ -12,8 +12,6 @@ import ( "path/filepath" "strings" - "forgejo.org/modules/container" - "gopkg.in/yaml.v3" ) @@ -34,15 +32,13 @@ type loader struct { fixtureFiles []*fixtureFile } -func newFixtureLoader(db *sql.DB, dialect string, fixturePaths []string, allTableNames container.Set[string]) (*loader, error) { +func newFixtureLoader(db *sql.DB, dialect string, fixturePaths []string) (*loader, error) { l := &loader{ db: db, dialect: dialect, fixtureFiles: []*fixtureFile{}, } - tablesWithoutFixture := allTableNames - // Load fixtures for _, fixturePath := range fixturePaths { stat, err := os.Stat(fixturePath) @@ -64,7 +60,6 @@ func newFixtureLoader(db *sql.DB, dialect string, fixturePaths []string, allTabl return nil, err } l.fixtureFiles = append(l.fixtureFiles, fixtureFile) - tablesWithoutFixture.Remove(fixtureFile.name) } } } else { @@ -76,14 +71,6 @@ func newFixtureLoader(db *sql.DB, dialect string, fixturePaths []string, allTabl } } - // Even though these tables have no fixtures, they can still be used and ensure - // they are cleaned. - for table := range tablesWithoutFixture.Seq() { - l.fixtureFiles = append(l.fixtureFiles, &fixtureFile{ - name: table, - }) - } - return l, nil } @@ -191,13 +178,13 @@ func (l *loader) Load() error { }() // Clean the table and re-insert the fixtures. - tableDeleted := make(container.Set[string]) + tableDeleted := map[string]struct{}{} for _, fixture := range l.fixtureFiles { - if !tableDeleted.Contains(fixture.name) { + if _, ok := tableDeleted[fixture.name]; !ok { if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", l.quoteKeyword(fixture.name))); err != nil { return fmt.Errorf("cannot delete table %s: %w", fixture.name, err) } - tableDeleted.Add(fixture.name) + tableDeleted[fixture.name] = struct{}{} } for _, insertSQL := range fixture.insertSQLs { diff --git a/models/unittest/fixtures.go b/models/unittest/fixtures.go index 829cc16466..6dc5c8412d 100644 --- a/models/unittest/fixtures.go +++ b/models/unittest/fixtures.go @@ -7,12 +7,10 @@ package unittest import ( "fmt" "path/filepath" - "sync" "time" "forgejo.org/models/db" "forgejo.org/modules/auth/password/hash" - "forgejo.org/modules/container" "forgejo.org/modules/setting" "xorm.io/xorm" @@ -46,8 +44,6 @@ func OverrideFixtures(dir string) func() { } } -var allTableNames = sync.OnceValue(db.GetTableNames) - // InitFixtures initialize test fixtures for a test database func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) { e, err := GetXORMEngine(engine...) @@ -79,12 +75,7 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) { panic("Unsupported RDBMS for test") } - var allTables container.Set[string] - if !opts.SkipCleanRegistedModels { - allTables = allTableNames().Clone() - } - - fixturesLoader, err = newFixtureLoader(e.DB().DB, dialect, fixturePaths, allTables) + fixturesLoader, err = newFixtureLoader(e.DB().DB, dialect, fixturePaths) if err != nil { return err } diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index 29ec82c55f..d34c9e9a0a 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -217,10 +217,6 @@ type FixturesOptions struct { Files []string Dirs []string Base string - // By default all registered models are cleaned, even if they do not have - // fixture. Enabling this will skip that and only models with fixtures are - // considered. - SkipCleanRegistedModels bool } // CreateTestEngine creates a memory database and loads the fixture data from fixturesDir diff --git a/models/user/activitypub.go b/models/user/activitypub.go index aabf2336fc..816fd8a098 100644 --- a/models/user/activitypub.go +++ b/models/user/activitypub.go @@ -19,7 +19,7 @@ func (u *User) APActorID() string { return fmt.Sprintf("%sapi/v1/activitypub/user-id/%s", setting.AppURL, url.PathEscape(fmt.Sprintf("%d", u.ID))) } -// KeyID returns the ID of the user's public key -func (u *User) KeyID() string { +// APActorKeyID returns the ID of the user's public key +func (u *User) APActorKeyID() string { return u.APActorID() + "#main-key" } diff --git a/models/user/email_address_test.go b/models/user/email_address_test.go index 85f5b16c65..1801f57a23 100644 --- a/models/user/email_address_test.go +++ b/models/user/email_address_test.go @@ -181,20 +181,3 @@ func TestDeletePrimaryEmailAddressOfUser(t *testing.T) { assert.True(t, user_model.IsErrEmailAddressNotExist(err)) assert.Nil(t, email) } - -func TestActivateUserEmail(t *testing.T) { - defer unittest.OverrideFixtures("models/fixtures/TestActivateUserEmail")() - require.NoError(t, unittest.PrepareTestDatabase()) - - t.Run("Activate email", func(t *testing.T) { - require.NoError(t, user_model.ActivateUserEmail(t.Context(), 1001, "AnotherTestUserWithUpperCaseEmail@otto.splvs.net", true)) - - unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{UID: 1001}, "is_activated = true") - }) - - t.Run("Deactivate email", func(t *testing.T) { - require.NoError(t, user_model.ActivateUserEmail(t.Context(), 1001, "AnotherTestUserWithUpperCaseEmail@otto.splvs.net", false)) - - unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{UID: 1001}, "is_activated = false") - }) -} diff --git a/models/user/user.go b/models/user/user.go index b124572bb6..eedd1db80e 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -182,11 +182,11 @@ func (u *User) BeforeUpdate() { u.MaxRepoCreation = -1 } - // Ensure AvatarEmail is set for non-organization users, because organization - // are not required to have a email set. + // Organization does not need email + u.Email = strings.ToLower(u.Email) if !u.IsOrganization() { if len(u.AvatarEmail) == 0 { - u.AvatarEmail = strings.ToLower(u.Email) + u.AvatarEmail = u.Email } } diff --git a/models/user/user_repository.go b/models/user/user_repository.go index 85f44f1598..3f24efb1fb 100644 --- a/models/user/user_repository.go +++ b/models/user/user_repository.go @@ -57,6 +57,14 @@ func CreateFederatedUser(ctx context.Context, user *User, federatedUser *Federat return committer.Commit() } +func (federatedUser *FederatedUser) UpdateFederatedUser(ctx context.Context) error { + if _, err := validation.IsValid(federatedUser); err != nil { + return err + } + _, err := db.GetEngine(ctx).ID(federatedUser.ID).Cols("inbox_path").Update(federatedUser) + return err +} + func FindFederatedUser(ctx context.Context, externalID string, federationHostID int64) (*User, *FederatedUser, error) { federatedUser := new(FederatedUser) user := new(User) @@ -211,6 +219,7 @@ func RemoveFollower(ctx context.Context, followedUser *User, followingUser *Fede return err } +// TODO: We should unify Activity-pub-following and classical following (see models/user/follow.go) func IsFollowingAp(ctx context.Context, followedUser *User, followingUser *FederatedUser) (bool, error) { if res, err := validation.IsValid(followedUser); !res { return false, err diff --git a/models/user/user_test.go b/models/user/user_test.go index f9a3aa6075..fd9d05653f 100644 --- a/models/user/user_test.go +++ b/models/user/user_test.go @@ -150,7 +150,7 @@ func TestAPActorID_APActorID(t *testing.T) { func TestKeyID(t *testing.T) { user := user_model.User{ID: 1} - url := user.KeyID() + url := user.APActorKeyID() expected := "https://try.gitea.io/api/v1/activitypub/user-id/1#main-key" assert.Equal(t, expected, url) } diff --git a/modules/activitypub/client.go b/modules/activitypub/client.go index fb6fa8b543..d015fb7bec 100644 --- a/modules/activitypub/client.go +++ b/modules/activitypub/client.go @@ -89,7 +89,6 @@ func NewClientFactory() (c *ClientFactory, err error) { type APClientFactory interface { WithKeys(ctx context.Context, user *user_model.User, pubID string) (APClient, error) - WithKeysDirect(ctx context.Context, privateKey, pubID string) (APClient, error) } // Client struct @@ -104,8 +103,12 @@ type Client struct { } // NewRequest function -func (cf *ClientFactory) WithKeysDirect(ctx context.Context, privateKey, pubID string) (APClient, error) { - privPem, _ := pem.Decode([]byte(privateKey)) +func (cf *ClientFactory) WithKeys(ctx context.Context, user *user_model.User, pubID string) (APClient, error) { + priv, err := GetPrivateKey(ctx, user) + if err != nil { + return nil, err + } + privPem, _ := pem.Decode([]byte(priv)) privParsed, err := x509.ParsePKCS1PrivateKey(privPem.Bytes) if err != nil { return nil, err @@ -123,14 +126,6 @@ func (cf *ClientFactory) WithKeysDirect(ctx context.Context, privateKey, pubID s return &c, nil } -func (cf *ClientFactory) WithKeys(ctx context.Context, user *user_model.User, pubID string) (APClient, error) { - priv, err := GetPrivateKey(ctx, user) - if err != nil { - return nil, err - } - return cf.WithKeysDirect(ctx, priv, pubID) -} - // NewRequest function func (c *Client) newRequest(method string, b []byte, to string) (req *http.Request, err error) { buf := bytes.NewBuffer(b) @@ -154,14 +149,12 @@ func (c *Client) Post(b []byte, to string) (resp *http.Response, err error) { return nil, err } - if c.pubID != "" { - signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.postHeaders, httpsig.Signature, httpsigExpirationTime) - if err != nil { - return nil, err - } - if err := signer.SignRequest(c.priv, c.pubID, req, b); err != nil { - return nil, err - } + signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.postHeaders, httpsig.Signature, httpsigExpirationTime) + if err != nil { + return nil, err + } + if err := signer.SignRequest(c.priv, c.pubID, req, b); err != nil { + return nil, err } resp, err = c.client.Do(req) @@ -174,15 +167,12 @@ func (c *Client) Get(to string) (resp *http.Response, err error) { if req, err = c.newRequest(http.MethodGet, nil, to); err != nil { return nil, err } - - if c.pubID != "" { - signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.getHeaders, httpsig.Signature, httpsigExpirationTime) - if err != nil { - return nil, err - } - if err := signer.SignRequest(c.priv, c.pubID, req, nil); err != nil { - return nil, err - } + signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.getHeaders, httpsig.Signature, httpsigExpirationTime) + if err != nil { + return nil, err + } + if err := signer.SignRequest(c.priv, c.pubID, req, nil); err != nil { + return nil, err } resp, err = c.client.Do(req) diff --git a/modules/container/set.go b/modules/container/set.go index d3719dc552..70f837bc66 100644 --- a/modules/container/set.go +++ b/modules/container/set.go @@ -74,8 +74,3 @@ func (s Set[T]) Values() []T { func (s Set[T]) Seq() iter.Seq[T] { return maps.Keys(s) } - -// Clone returns a identical shallow copy of this set. -func (s Set[T]) Clone() Set[T] { - return maps.Clone(s) -} diff --git a/modules/container/set_test.go b/modules/container/set_test.go index 44e4847f6b..af5e9126ab 100644 --- a/modules/container/set_test.go +++ b/modules/container/set_test.go @@ -47,11 +47,4 @@ func TestSet(t *testing.T) { assert.False(t, s.IsSubset([]string{"key1"})) assert.True(t, s.IsSubset([]string{})) - - t.Run("Clone", func(t *testing.T) { - clonedSet := s.Clone() - clonedSet.Remove("key6") - assert.False(t, clonedSet.Contains("key6")) - assert.True(t, s.Contains("key6")) - }) } diff --git a/modules/git/blame.go b/modules/git/blame.go index 868edab2b8..4ff347e31b 100644 --- a/modules/git/blame.go +++ b/modules/git/blame.go @@ -132,7 +132,7 @@ func (r *BlameReader) Close() error { // CreateBlameReader creates reader for given repository, commit and file func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath string, commit *Commit, file string, bypassBlameIgnore bool) (*BlameReader, error) { var ignoreRevsFile *string - if !bypassBlameIgnore { + if CheckGitVersionAtLeast("2.23") == nil && !bypassBlameIgnore { ignoreRevsFile = tryCreateBlameIgnoreRevsFile(commit) } diff --git a/modules/git/blob.go b/modules/git/blob.go index 4eef5f0e2a..8c5c275146 100644 --- a/modules/git/blob.go +++ b/modules/git/blob.go @@ -8,7 +8,6 @@ import ( "bufio" "bytes" "encoding/base64" - "fmt" "io" "forgejo.org/modules/log" @@ -173,43 +172,60 @@ func (b *Blob) GetBlobContent(limit int64) (string, error) { return string(buf), err } -type BlobTooLargeError struct { - Size, Limit int64 -} - -func (b BlobTooLargeError) Error() string { - return fmt.Sprintf("blob: content larger than limit (%d > %d)", b.Size, b.Limit) -} - -// 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, - } +// GetBlobLineCount gets line count of the blob +func (b *Blob) GetBlobLineCount() (int, error) { + reader, err := b.DataAsync() + if err != nil { + return 0, err } + defer reader.Close() + buf := make([]byte, 32*1024) + count := 1 + lineSep := []byte{'\n'} - rc, size, err := b.NewTruncatedReader(limit) + c, err := reader.Read(buf) + if c == 0 && err == io.EOF { + return 0, nil + } + for { + count += bytes.Count(buf[:c], lineSep) + switch { + case err == io.EOF: + return count, nil + case err != nil: + return count, err + } + c, err = reader.Read(buf) + } +} + +// GetBlobContentBase64 Reads the content of the blob with a base64 encode and returns the encoded string +func (b *Blob) GetBlobContentBase64() (string, error) { + dataRc, err := b.DataAsync() if err != nil { return "", err } - defer rc.Close() + defer dataRc.Close() - encoding := base64.StdEncoding - buf := bytes.NewBuffer(make([]byte, 0, encoding.EncodedLen(int(size)))) + pr, pw := io.Pipe() + encoder := base64.NewEncoder(base64.StdEncoding, pw) - encoder := base64.NewEncoder(encoding, buf) + go func() { + _, err := io.Copy(encoder, dataRc) + _ = encoder.Close() - if _, err := io.Copy(encoder, rc); err != nil { + if err != nil { + _ = pw.CloseWithError(err) + } else { + _ = pw.Close() + } + }() + + out, err := io.ReadAll(pr) + if err != nil { return "", err } - if err := encoder.Close(); err != nil { - return "", err - } - - return buf.String(), nil + return string(out), nil } // GuessContentType guesses the content type of the blob. @@ -220,7 +236,7 @@ func (b *Blob) GuessContentType() (typesniffer.SniffedType, error) { } defer r.Close() - return typesniffer.DetectContentTypeFromReader(r, b.Name()) + return typesniffer.DetectContentTypeFromReader(r) } // GetBlob finds the blob object in the repository. diff --git a/modules/git/blob_test.go b/modules/git/blob_test.go index a4b8033941..54115013d3 100644 --- a/modules/git/blob_test.go +++ b/modules/git/blob_test.go @@ -63,24 +63,6 @@ func TestBlob(t *testing.T) { require.Equal(t, "file2\n", r) }) - t.Run("GetContentBase64", func(t *testing.T) { - r, err := testBlob.GetContentBase64(100) - require.NoError(t, err) - require.Equal(t, "ZmlsZTIK", r) - - r, err = testBlob.GetContentBase64(-1) - require.ErrorAs(t, err, &BlobTooLargeError{}) - require.Empty(t, r) - - r, err = testBlob.GetContentBase64(4) - require.ErrorAs(t, err, &BlobTooLargeError{}) - require.Empty(t, r) - - r, err = testBlob.GetContentBase64(6) - require.NoError(t, err) - require.Equal(t, "ZmlsZTIK", r) - }) - t.Run("NewTruncatedReader", func(t *testing.T) { // read fewer than available rc, size, err := testBlob.NewTruncatedReader(100) diff --git a/modules/git/commit.go b/modules/git/commit.go index 1228b4523b..96831e3ae4 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -412,7 +412,11 @@ func (c *Commit) GetSubModule(entryname string) (string, error) { // GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only') func (c *Commit) GetBranchName() (string, error) { - cmd := NewCommand(c.repo.Ctx, "name-rev", "--exclude", "refs/tags/*", "--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) + cmd := NewCommand(c.repo.Ctx, "name-rev") + if CheckGitVersionAtLeast("2.13.0") == nil { + cmd.AddArguments("--exclude", "refs/tags/*") + } + cmd.AddArguments("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) data, _, err := cmd.RunStdString(&RunOpts{Dir: c.repo.Path}) if err != nil { // handle special case where git can not describe commit diff --git a/modules/git/git.go b/modules/git/git.go index 851b090b53..1dfd0b5134 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -23,7 +23,7 @@ import ( ) // RequiredVersion is the minimum Git version required -const RequiredVersion = "2.34.1" +const RequiredVersion = "2.0.0" var ( // GitExecutable is the command name of git @@ -33,6 +33,7 @@ var ( // DefaultContext is the default context to run git commands in, must be initialized by git.InitXxx DefaultContext context.Context + SupportProcReceive bool // >= 2.29 SupportHashSha256 bool // >= 2.42, SHA-256 repositories no longer an ‘experimental curiosity’ InvertedGitFlushEnv bool // 2.43.1 SupportCheckAttrOnBare bool // >= 2.40 @@ -112,7 +113,7 @@ func VersionInfo() string { format := "%s" args := []any{GitVersion.Original()} // Since git wire protocol has been released from git v2.18 - if setting.Git.EnableAutoGitWireProtocol { + if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil { format += ", Wire Protocol %s Enabled" args = append(args, "Version 2") // for focus color } @@ -171,13 +172,16 @@ func InitFull(ctx context.Context) (err error) { _ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg")) } - if setting.Git.EnableAutoGitWireProtocol { + // Since git wire protocol has been released from git v2.18 + if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil { globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2") } // Explicitly disable credential helper, otherwise Git credentials might leak - globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=") - + if CheckGitVersionAtLeast("2.9") == nil { + globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=") + } + SupportProcReceive = CheckGitVersionAtLeast("2.29") == nil SupportHashSha256 = CheckGitVersionAtLeast("2.42") == nil SupportCheckAttrOnBare = CheckGitVersionAtLeast("2.40") == nil if SupportHashSha256 { @@ -191,6 +195,9 @@ func InitFull(ctx context.Context) (err error) { SupportGrepMaxCount = CheckGitVersionAtLeast("2.38") == nil if setting.LFS.StartServer { + if CheckGitVersionAtLeast("2.1.2") != nil { + return errors.New("LFS server support requires Git >= 2.1.2") + } globalCommandArgs = append(globalCommandArgs, "-c", "filter.lfs.required=", "-c", "filter.lfs.smudge=", "-c", "filter.lfs.clean=") } @@ -227,28 +234,38 @@ func syncGitConfig() (err error) { } } - // Set git some configurations - these must be set to these values for forgejo to work correctly + // Set git some configurations - these must be set to these values for gitea to work correctly if err := configSet("core.quotePath", "false"); err != nil { return err } - if err := configSet("receive.advertisePushOptions", "true"); err != nil { - return err + if CheckGitVersionAtLeast("2.10") == nil { + if err := configSet("receive.advertisePushOptions", "true"); err != nil { + return err + } } - if err := configSet("core.commitGraph", "true"); err != nil { - return err - } - if err := configSet("gc.writeCommitGraph", "true"); err != nil { - return err - } - if err := configSet("fetch.writeCommitGraph", "true"); err != nil { - return err + if CheckGitVersionAtLeast("2.18") == nil { + if err := configSet("core.commitGraph", "true"); err != nil { + return err + } + if err := configSet("gc.writeCommitGraph", "true"); err != nil { + return err + } + if err := configSet("fetch.writeCommitGraph", "true"); err != nil { + return err + } } - // set support for AGit flow - if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil { - return err + if SupportProcReceive { + // set support for AGit flow + if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil { + return err + } + } else { + if err := configUnsetAll("receive.procReceiveRefs", "refs/for"); err != nil { + return err + } } // Due to CVE-2022-24765, git now denies access to git directories which are not owned by current user @@ -267,6 +284,11 @@ func syncGitConfig() (err error) { switch setting.Repository.Signing.Format { case "ssh": + // First do a git version check. + if CheckGitVersionAtLeast("2.34.0") != nil { + return errors.New("ssh signing requires Git >= 2.34.0") + } + // Get the ssh-keygen binary that Git will use. // This can be overridden in app.ini in [git.config] section, so we must // query this information. @@ -303,7 +325,8 @@ func syncGitConfig() (err error) { } } - if !setting.Git.DisablePartialClone { + // By default partial clones are disabled, enable them from git v2.22 + if !setting.Git.DisablePartialClone && CheckGitVersionAtLeast("2.22") == nil { if err = configSet("uploadpack.allowfilter", "true"); err != nil { return err } diff --git a/modules/git/git_test.go b/modules/git/git_test.go index 38d4db169c..01200dba68 100644 --- a/modules/git/git_test.go +++ b/modules/git/git_test.go @@ -14,6 +14,7 @@ import ( "forgejo.org/modules/test" "forgejo.org/modules/util" + "github.com/hashicorp/go-version" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -104,6 +105,10 @@ func TestSyncConfigGPGFormat(t *testing.T) { }) t.Run("SSH format", func(t *testing.T) { + if CheckGitVersionAtLeast("2.34.0") != nil { + t.SkipNow() + } + r, err := os.OpenRoot(t.TempDir()) require.NoError(t, err) f, err := r.OpenFile("ssh-keygen", os.O_CREATE|os.O_TRUNC, 0o700) @@ -116,6 +121,13 @@ func TestSyncConfigGPGFormat(t *testing.T) { assert.True(t, gitConfigContains("[gpg]")) assert.True(t, gitConfigContains("format = ssh")) + t.Run("Old version", func(t *testing.T) { + oldVersion, err := version.NewVersion("2.33.0") + require.NoError(t, err) + defer test.MockVariableValue(&GitVersion, oldVersion)() + require.ErrorContains(t, syncGitConfig(), "ssh signing requires Git >= 2.34.0") + }) + t.Run("No ssh-keygen binary", func(t *testing.T) { require.NoError(t, r.Remove("ssh-keygen")) require.ErrorContains(t, syncGitConfig(), "git signing requires a ssh-keygen binary") diff --git a/modules/git/pipeline/revlist.go b/modules/git/pipeline/revlist.go index 1ee8921854..f39b7113bb 100644 --- a/modules/git/pipeline/revlist.go +++ b/modules/git/pipeline/revlist.go @@ -16,6 +16,26 @@ import ( "forgejo.org/modules/log" ) +// RevListAllObjects runs rev-list --objects --all and writes to a pipewriter +func RevListAllObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync.WaitGroup, basePath string, errChan chan<- error) { + defer wg.Done() + defer revListWriter.Close() + + stderr := new(bytes.Buffer) + var errbuf strings.Builder + cmd := git.NewCommand(ctx, "rev-list", "--objects", "--all") + if err := cmd.Run(&git.RunOpts{ + Dir: basePath, + Stdout: revListWriter, + Stderr: stderr, + }); err != nil { + log.Error("git rev-list --objects --all [%s]: %v - %s", basePath, err, errbuf.String()) + err = fmt.Errorf("git rev-list --objects --all [%s]: %w - %s", basePath, err, errbuf.String()) + _ = revListWriter.CloseWithError(err) + errChan <- err + } +} + // RevListObjects run rev-list --objects from headSHA to baseSHA func RevListObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync.WaitGroup, tmpBasePath, headSHA, baseSHA string, errChan chan<- error) { defer wg.Done() diff --git a/modules/git/remote.go b/modules/git/remote.go index 83a02fe2be..fb66d76ff0 100644 --- a/modules/git/remote.go +++ b/modules/git/remote.go @@ -12,7 +12,14 @@ import ( // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) { - result, _, err := NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName).RunStdString(&RunOpts{Dir: repoPath}) + var cmd *Command + if CheckGitVersionAtLeast("2.7") == nil { + cmd = NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName) + } else { + cmd = NewCommand(ctx, "config", "--get").AddDynamicArguments("remote." + remoteName + ".url") + } + + result, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath}) if err != nil { return "", err } diff --git a/modules/git/repo_attribute_test.go b/modules/git/repo_attribute_test.go index 3d2c845fa0..c69382e245 100644 --- a/modules/git/repo_attribute_test.go +++ b/modules/git/repo_attribute_test.go @@ -5,6 +5,7 @@ package git import ( "context" + "fmt" "io" "io/fs" "os" @@ -196,7 +197,7 @@ func TestGitAttributeCheckerError(t *testing.T) { path := t.TempDir() // we can't use unittest.CopyDir because of an import cycle (git.Init in unittest) - require.NoError(t, os.CopyFS(path, os.DirFS(filepath.Join(testReposDir, "language_stats_repo")))) + require.NoError(t, CopyFS(path, os.DirFS(filepath.Join(testReposDir, "language_stats_repo")))) gitRepo, err := openRepositoryWithDefaultContext(path) require.NoError(t, err) @@ -323,3 +324,32 @@ func TestGitAttributeCheckerError(t *testing.T) { require.ErrorIs(t, err, fs.ErrClosed) }) } + +// CopyFS is adapted from https://github.com/golang/go/issues/62484 +// which should be available with go1.23 +func CopyFS(dir string, fsys fs.FS) error { + return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, _ error) error { + targ := filepath.Join(dir, filepath.FromSlash(path)) + if d.IsDir() { + return os.MkdirAll(targ, 0o777) + } + r, err := fsys.Open(path) + if err != nil { + return err + } + defer r.Close() + info, err := r.Stat() + if err != nil { + return err + } + w, err := os.OpenFile(targ, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o666|info.Mode()&0o777) + if err != nil { + return err + } + if _, err := io.Copy(w, r); err != nil { + w.Close() + return fmt.Errorf("copying %s: %v", path, err) + } + return w.Close() + }) +} diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 41ca0e39b1..4c8516f828 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -443,18 +443,42 @@ func (repo *Repository) getCommitsBeforeLimit(id ObjectID, num int) ([]*Commit, } func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error) { - command := NewCommand(repo.Ctx, "for-each-ref", "--format=%(refname:strip=2)").AddOptionValues("--contains", commit.ID.String(), BranchPrefix) + if CheckGitVersionAtLeast("2.7.0") == nil { + command := NewCommand(repo.Ctx, "for-each-ref", "--format=%(refname:strip=2)").AddOptionValues("--contains", commit.ID.String(), BranchPrefix) - if limit != -1 { - command = command.AddOptionFormat("--count=%d", limit) + if limit != -1 { + command = command.AddOptionFormat("--count=%d", limit) + } + + stdout, _, err := command.RunStdString(&RunOpts{Dir: repo.Path}) + if err != nil { + return nil, err + } + + branches := strings.Fields(stdout) + return branches, nil } - stdout, _, err := command.RunStdString(&RunOpts{Dir: repo.Path}) + stdout, _, err := NewCommand(repo.Ctx, "branch").AddOptionValues("--contains", commit.ID.String()).RunStdString(&RunOpts{Dir: repo.Path}) if err != nil { return nil, err } - branches := strings.Fields(stdout) + refs := strings.Split(stdout, "\n") + + var max int + if len(refs) > limit { + max = limit + } else { + max = len(refs) - 1 + } + + branches := make([]string, max) + for i, ref := range refs[:max] { + parts := strings.Fields(ref) + + branches[i] = parts[len(parts)-1] + } return branches, nil } diff --git a/modules/git/repo_commitgraph.go b/modules/git/repo_commitgraph.go index c3647bd894..492438be37 100644 --- a/modules/git/repo_commitgraph.go +++ b/modules/git/repo_commitgraph.go @@ -11,8 +11,10 @@ import ( // WriteCommitGraph write commit graph to speed up repo access // this requires git v2.18 to be installed func WriteCommitGraph(ctx context.Context, repoPath string) error { - if _, _, err := NewCommand(ctx, "commit-graph", "write").RunStdString(&RunOpts{Dir: repoPath}); err != nil { - return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err) + if CheckGitVersionAtLeast("2.18") == nil { + if _, _, err := NewCommand(ctx, "commit-graph", "write").RunStdString(&RunOpts{Dir: repoPath}); err != nil { + return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err) + } } return nil } diff --git a/modules/git/tree_entry.go b/modules/git/tree_entry.go index ec5c632ca0..d51b7992fe 100644 --- a/modules/git/tree_entry.go +++ b/modules/git/tree_entry.go @@ -116,37 +116,32 @@ func (te *TreeEntry) Type() string { } } -// LinkTarget returns the target of the symlink as string. -func (te *TreeEntry) LinkTarget() (string, error) { - if !te.IsLink() { - return "", ErrBadLink{te.Name(), "not a symlink"} - } - - const symlinkLimit = 4096 // according to git config core.longpaths https://stackoverflow.com/a/22575737 - blob := te.Blob() - if blob.Size() > symlinkLimit { - return "", ErrBadLink{te.Name(), "symlink too large"} - } - - rc, size, err := blob.NewTruncatedReader(symlinkLimit) - if err != nil { - return "", err - } - defer rc.Close() - - buf := make([]byte, int(size)) - _, err = io.ReadFull(rc, buf) - return string(buf), err -} - // FollowLink returns the entry pointed to by a symlink func (te *TreeEntry) FollowLink() (*TreeEntry, string, error) { + if !te.IsLink() { + return nil, "", ErrBadLink{te.Name(), "not a symlink"} + } + // read the link - lnk, err := te.LinkTarget() + r, err := te.Blob().DataAsync() if err != nil { return nil, "", err } + closed := false + defer func() { + if !closed { + _ = r.Close() + } + }() + buf := make([]byte, te.Size()) + _, err = io.ReadFull(r, buf) + if err != nil { + return nil, "", err + } + _ = r.Close() + closed = true + lnk := string(buf) t := te.ptree // traverse up directories diff --git a/modules/httplib/serve.go b/modules/httplib/serve.go index d385ac21c9..c5f0658d4e 100644 --- a/modules/httplib/serve.go +++ b/modules/httplib/serve.go @@ -99,7 +99,7 @@ func setServeHeadersByFile(r *http.Request, w http.ResponseWriter, filePath stri Filename: path.Base(filePath), } - sniffedType := typesniffer.DetectContentType(mineBuf, opts.Filename) + sniffedType := typesniffer.DetectContentType(mineBuf) // the "render" parameter came from year 2016: 638dd24c, it doesn't have clear meaning, so I think it could be removed later isPlain := sniffedType.IsText() || r.FormValue("render") != "" diff --git a/modules/indexer/code/bleve/bleve.go b/modules/indexer/code/bleve/bleve.go index 4c8b5f2a86..c53b7a2e6d 100644 --- a/modules/indexer/code/bleve/bleve.go +++ b/modules/indexer/code/bleve/bleve.go @@ -177,7 +177,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro fileContents, err := io.ReadAll(io.LimitReader(batchReader, size)) if err != nil { return err - } else if !typesniffer.DetectContentType(fileContents, update.Filename).IsText() { + } else if !typesniffer.DetectContentType(fileContents).IsText() { // FIXME: UTF-16 files will probably fail here // Even if the file is not recognized as a "text file", we could still put its name into the indexers to make the filename become searchable, while leave the content to empty. fileContents = nil diff --git a/modules/indexer/code/elasticsearch/elasticsearch.go b/modules/indexer/code/elasticsearch/elasticsearch.go index 9b11f56fb7..3903d77fe0 100644 --- a/modules/indexer/code/elasticsearch/elasticsearch.go +++ b/modules/indexer/code/elasticsearch/elasticsearch.go @@ -144,7 +144,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro fileContents, err := io.ReadAll(io.LimitReader(batchReader, size)) if err != nil { return nil, err - } else if !typesniffer.DetectContentType(fileContents, update.Filename).IsText() { + } else if !typesniffer.DetectContentType(fileContents).IsText() { // FIXME: UTF-16 files will probably fail here return nil, nil } diff --git a/modules/indexer/issues/bleve/bleve.go b/modules/indexer/issues/bleve/bleve.go index cb98f722c5..573d63a446 100644 --- a/modules/indexer/issues/bleve/bleve.go +++ b/modules/indexer/issues/bleve/bleve.go @@ -156,12 +156,11 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error { func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (*internal.SearchResult, error) { var queries []query.Query - tokens, err := options.Tokens() - if err != nil { - return nil, err - } - - if len(tokens) > 0 { + if options.Keyword != "" { + tokens, err := options.Tokens() + if err != nil { + return nil, err + } q := bleve.NewBooleanQuery() for _, token := range tokens { innerQ := bleve.NewDisjunctionQuery( @@ -171,7 +170,7 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( if issueID, err := token.ParseIssueReference(); err == nil { idQuery := inner_bleve.NumericEqualityQuery(issueID, "index") - idQuery.SetBoost(20.0) + idQuery.SetBoost(5.0) innerQ.AddQuery(idQuery) } @@ -198,15 +197,6 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( queries = append(queries, bleve.NewDisjunctionQuery(repoQueries...)) } - if options.PriorityRepoID.Has() { - eq := inner_bleve.NumericEqualityQuery(options.PriorityRepoID.Value(), "repo_id") - eq.SetBoost(10.0) - meh := bleve.NewMatchAllQuery() - meh.SetBoost(0) - should := bleve.NewDisjunctionQuery(eq, meh) - queries = append(queries, should) - } - if options.IsPull.Has() { queries = append(queries, inner_bleve.BoolFieldQuery(options.IsPull.Value(), "is_pull")) } diff --git a/modules/indexer/issues/db/db.go b/modules/indexer/issues/db/db.go index 5f42bce9a1..397daa3265 100644 --- a/modules/indexer/issues/db/db.go +++ b/modules/indexer/issues/db/db.go @@ -53,7 +53,6 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( cond := builder.NewCond() - var priorityIssueIndex int64 if options.Keyword != "" { repoCond := builder.In("repo_id", options.RepoIDs) if len(options.RepoIDs) == 1 { @@ -83,7 +82,6 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( builder.Eq{"`index`": issueID}, cond, ) - priorityIssueIndex = issueID } } @@ -91,7 +89,6 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( if err != nil { return nil, err } - opt.PriorityIssueIndex = priorityIssueIndex // If pagesize == 0, return total count only. It's a special case for search count. if options.Paginator != nil && options.Paginator.PageSize == 0 { diff --git a/modules/indexer/issues/db/options.go b/modules/indexer/issues/db/options.go index 55a471fc8e..4411cc1c37 100644 --- a/modules/indexer/issues/db/options.go +++ b/modules/indexer/issues/db/options.go @@ -78,11 +78,6 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m User: nil, } - if options.PriorityRepoID.Has() { - opts.SortType = "priorityrepo" - opts.PriorityRepoID = options.PriorityRepoID.Value() - } - if len(options.MilestoneIDs) == 1 && options.MilestoneIDs[0] == 0 { opts.MilestoneIDs = []int64{db.NoConditionID} } else { diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go index 311e92730e..9d2786e101 100644 --- a/modules/indexer/issues/elasticsearch/elasticsearch.go +++ b/modules/indexer/issues/elasticsearch/elasticsearch.go @@ -149,13 +149,12 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error { func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (*internal.SearchResult, error) { query := elastic.NewBoolQuery() - tokens, err := options.Tokens() - if err != nil { - return nil, err - } - - if len(tokens) > 0 { + if options.Keyword != "" { q := elastic.NewBoolQuery() + tokens, err := options.Tokens() + if err != nil { + return nil, err + } for _, token := range tokens { innerQ := elastic.NewMultiMatchQuery(token.Term, "content", "comments").FieldWithBoost("title", 2.0).TieBreaker(0.5) if token.Fuzzy { @@ -166,7 +165,7 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( } var eitherQ elastic.Query = innerQ if issueID, err := token.ParseIssueReference(); err == nil { - indexQ := elastic.NewTermQuery("index", issueID).Boost(20) + indexQ := elastic.NewTermQuery("index", issueID).Boost(15.0) eitherQ = elastic.NewDisMaxQuery().Query(indexQ).Query(innerQ).TieBreaker(0.5) } switch token.Kind { @@ -189,10 +188,6 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( } query.Must(q) } - if options.PriorityRepoID.Has() { - q := elastic.NewTermQuery("repo_id", options.PriorityRepoID.Value()).Boost(10) - query.Should(q) - } if options.IsPull.Has() { query.Must(elastic.NewTermQuery("is_pull", options.IsPull.Value())) diff --git a/modules/indexer/issues/internal/model.go b/modules/indexer/issues/internal/model.go index cdd113212d..6c55405179 100644 --- a/modules/indexer/issues/internal/model.go +++ b/modules/indexer/issues/internal/model.go @@ -75,9 +75,8 @@ type SearchResult struct { type SearchOptions struct { Keyword string // keyword to search - RepoIDs []int64 // repository IDs which the issues belong to - AllPublic bool // if include all public repositories - PriorityRepoID optional.Option[int64] // issues from this repository will be prioritized when SortByScore + RepoIDs []int64 // repository IDs which the issues belong to + AllPublic bool // if include all public repositories IsPull optional.Option[bool] // if the issues is a pull request IsClosed optional.Option[bool] // if the issues is closed diff --git a/modules/indexer/issues/internal/qstring.go b/modules/indexer/issues/internal/qstring.go index 348f7a564b..6b60b4c5f6 100644 --- a/modules/indexer/issues/internal/qstring.go +++ b/modules/indexer/issues/internal/qstring.go @@ -45,9 +45,12 @@ func (t *Tokenizer) next() (tk Token, err error) { // skip all leading white space for { - if r, _, err = t.in.ReadRune(); err != nil || r != ' ' { - break + if r, _, err = t.in.ReadRune(); err == nil && r == ' ' { + //nolint:staticcheck,wastedassign // SA4006 the variable is used after the loop + r, _, err = t.in.ReadRune() + continue } + break } if err != nil { return tk, err @@ -104,17 +107,11 @@ nextEnd: // Tokenize the keyword func (o *SearchOptions) Tokens() (tokens []Token, err error) { - if o.Keyword == "" { - return nil, nil - } - in := strings.NewReader(o.Keyword) it := Tokenizer{in: in} for token, err := it.next(); err == nil; token, err = it.next() { - if token.Term != "" { - tokens = append(tokens, token) - } + tokens = append(tokens, token) } if err != nil && err != io.EOF { return nil, err diff --git a/modules/indexer/issues/internal/qstring_test.go b/modules/indexer/issues/internal/qstring_test.go index eb4bdb306f..835491707c 100644 --- a/modules/indexer/issues/internal/qstring_test.go +++ b/modules/indexer/issues/internal/qstring_test.go @@ -41,36 +41,6 @@ var testOpts = []testIssueQueryStringOpt{ }, }, }, - { - Keyword: "Hello World", - Results: []Token{ - { - Term: "Hello", - Fuzzy: true, - Kind: BoolOptShould, - }, - { - Term: "World", - Fuzzy: true, - Kind: BoolOptShould, - }, - }, - }, - { - Keyword: " Hello World ", - Results: []Token{ - { - Term: "Hello", - Fuzzy: true, - Kind: BoolOptShould, - }, - { - Term: "World", - Fuzzy: true, - Kind: BoolOptShould, - }, - }, - }, { Keyword: "+Hello +World", Results: []Token{ @@ -186,68 +156,6 @@ var testOpts = []testIssueQueryStringOpt{ }, }, }, - { - Keyword: "\\", - Results: nil, - }, - { - Keyword: "\"", - Results: nil, - }, - { - Keyword: "Hello \\", - Results: []Token{ - { - Term: "Hello", - Fuzzy: true, - Kind: BoolOptShould, - }, - }, - }, - { - Keyword: "\"\"", - Results: nil, - }, - { - Keyword: "\" World \"", - Results: []Token{ - { - Term: " World ", - Fuzzy: false, - Kind: BoolOptShould, - }, - }, - }, - { - Keyword: "\"\" World \"\"", - Results: []Token{ - { - Term: "World", - Fuzzy: true, - Kind: BoolOptShould, - }, - }, - }, - { - Keyword: "Best \"Hello World\" Ever", - Results: []Token{ - { - Term: "Best", - Fuzzy: true, - Kind: BoolOptShould, - }, - { - Term: "Hello World", - Fuzzy: false, - Kind: BoolOptShould, - }, - { - Term: "Ever", - Fuzzy: true, - Kind: BoolOptShould, - }, - }, - }, } func TestIssueQueryString(t *testing.T) { diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go index 46014994a0..ef75955a14 100644 --- a/modules/indexer/issues/internal/tests/tests.go +++ b/modules/indexer/issues/internal/tests/tests.go @@ -87,44 +87,14 @@ func TestIndexer(t *testing.T, indexer internal.Indexer) { } } -func allResults(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { - assert.Len(t, result.Hits, len(data)) - assert.Equal(t, len(data), int(result.Total)) -} - var cases = []*testIndexerCase{ { Name: "default", SearchOptions: &internal.SearchOptions{}, - Expected: allResults, - }, - { - Name: "empty keyword", - SearchOptions: &internal.SearchOptions{ - Keyword: "", + Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { + assert.Len(t, result.Hits, len(data)) + assert.Equal(t, len(data), int(result.Total)) }, - Expected: allResults, - }, - { - Name: "whitespace keyword", - SearchOptions: &internal.SearchOptions{ - Keyword: " ", - }, - Expected: allResults, - }, - { - Name: "dangling slash in keyword", - SearchOptions: &internal.SearchOptions{ - Keyword: "\\", - }, - Expected: allResults, - }, - { - Name: "dangling quote in keyword", - SearchOptions: &internal.SearchOptions{ - Keyword: "\"", - }, - Expected: allResults, }, { Name: "empty", @@ -772,25 +742,6 @@ var cases = []*testIndexerCase{ } }, }, - { - Name: "PriorityRepoID", - SearchOptions: &internal.SearchOptions{ - IsPull: optional.Some(false), - IsClosed: optional.Some(false), - PriorityRepoID: optional.Some(int64(3)), - Paginator: &db.ListOptionsAll, - SortBy: internal.SortByScore, - }, - Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { - for i, v := range result.Hits { - if i < 7 { - assert.Equal(t, int64(3), data[v.ID].RepoID) - } else { - assert.NotEqual(t, int64(3), data[v.ID].RepoID) - } - } - }, - }, } type testIndexerCase struct { diff --git a/modules/lfs/pointer_scanner.go b/modules/lfs/pointer_scanner.go index 80da8e5222..632ecd19ae 100644 --- a/modules/lfs/pointer_scanner.go +++ b/modules/lfs/pointer_scanner.go @@ -39,7 +39,16 @@ func SearchPointerBlobs(ctx context.Context, repo *git.Repository, pointerChan c go pipeline.BlobsLessThan1024FromCatFileBatchCheck(catFileCheckReader, shasToBatchWriter, &wg) // 1. Run batch-check on all objects in the repository - go pipeline.CatFileBatchCheckAllObjects(ctx, catFileCheckWriter, &wg, basePath, errChan) + if git.CheckGitVersionAtLeast("2.6.0") != nil { + revListReader, revListWriter := io.Pipe() + shasToCheckReader, shasToCheckWriter := io.Pipe() + wg.Add(2) + go pipeline.CatFileBatchCheck(ctx, shasToCheckReader, catFileCheckWriter, &wg, basePath) + go pipeline.BlobsFromRevListObjects(revListReader, shasToCheckWriter, &wg) + go pipeline.RevListAllObjects(ctx, revListWriter, &wg, basePath, errChan) + } else { + go pipeline.CatFileBatchCheckAllObjects(ctx, catFileCheckWriter, &wg, basePath, errChan) + } wg.Wait() close(pointerChan) diff --git a/modules/log/event_writer.go b/modules/log/event_writer.go index 32b5b582c5..4b77e488de 100644 --- a/modules/log/event_writer.go +++ b/modules/log/event_writer.go @@ -26,7 +26,6 @@ type WriterMode struct { Flags Flags Expression string - Exclusion string StacktraceLevel Level diff --git a/modules/log/event_writer_base.go b/modules/log/event_writer_base.go index 4de2b953c7..9189ca4e90 100644 --- a/modules/log/event_writer_base.go +++ b/modules/log/event_writer_base.go @@ -68,14 +68,6 @@ func (b *EventWriterBaseImpl) Run(ctx context.Context) { } } - var exclusionRegexp *regexp.Regexp - if b.Mode.Exclusion != "" { - var err error - if exclusionRegexp, err = regexp.Compile(b.Mode.Exclusion); err != nil { - FallbackErrorf("unable to compile exclusion %q for writer %q: %v", b.Mode.Exclusion, b.Name, err) - } - } - handlePaused := func() { if pause := b.GetPauseChan(); pause != nil { select { @@ -103,13 +95,6 @@ func (b *EventWriterBaseImpl) Run(ctx context.Context) { continue } } - if exclusionRegexp != nil { - fileLineCaller := fmt.Sprintf("%s:%d:%s", event.Origin.Filename, event.Origin.Line, event.Origin.Caller) - matched := exclusionRegexp.MatchString(fileLineCaller) || exclusionRegexp.MatchString(event.Origin.MsgSimpleText) - if matched { - continue - } - } var err error switch msg := event.Msg.(type) { diff --git a/modules/log/event_writer_buffer_test.go b/modules/log/event_writer_buffer_test.go index d1e37c3673..ba9455ba69 100644 --- a/modules/log/event_writer_buffer_test.go +++ b/modules/log/event_writer_buffer_test.go @@ -31,49 +31,3 @@ func TestBufferLogger(t *testing.T) { logger.Close() assert.Contains(t, bufferWriter.Buffer.String(), expected) } - -func TestBufferLoggerWithExclusion(t *testing.T) { - prefix := "ExclusionPrefix " - level := log.INFO - message := "something" - - bufferWriter := log.NewEventWriterBuffer("test-buffer", log.WriterMode{ - Level: level, - Prefix: prefix, - Exclusion: message, - }) - - logger := log.NewLoggerWithWriters(t.Context(), "test", bufferWriter) - - logger.SendLogEvent(&log.Event{ - Level: log.INFO, - MsgSimpleText: message, - }) - logger.Close() - assert.NotContains(t, bufferWriter.Buffer.String(), message) -} - -func TestBufferLoggerWithExpressionAndExclusion(t *testing.T) { - prefix := "BothPrefix " - level := log.INFO - expression := ".*foo.*" - exclusion := ".*bar.*" - - bufferWriter := log.NewEventWriterBuffer("test-buffer", log.WriterMode{ - Level: level, - Prefix: prefix, - Expression: expression, - Exclusion: exclusion, - }) - - logger := log.NewLoggerWithWriters(t.Context(), "test", bufferWriter) - - logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "foo expression"}) - logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "bar exclusion"}) - logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "foo bar both"}) - logger.SendLogEvent(&log.Event{Level: log.INFO, MsgSimpleText: "none"}) - logger.Close() - - assert.Contains(t, bufferWriter.Buffer.String(), "foo expression") - assert.NotContains(t, bufferWriter.Buffer.String(), "bar") -} diff --git a/modules/log/logger_test.go b/modules/log/logger_test.go index 99045b0f4f..6d6ceb69d7 100644 --- a/modules/log/logger_test.go +++ b/modules/log/logger_test.go @@ -143,19 +143,3 @@ func TestLoggerExpressionFilter(t *testing.T) { assert.Equal(t, []string{"foo\n", "foo bar\n", "by filename\n"}, w1.GetLogs()) } - -func TestLoggerExclusionFilter(t *testing.T) { - logger := NewLoggerWithWriters(t.Context(), "test") - - w1 := newDummyWriter("dummy-1", DEBUG, 0) - w1.Mode.Exclusion = "foo.*" - logger.AddWriters(w1) - - logger.Info("foo") - logger.Info("bar") - logger.Info("foo bar") - logger.SendLogEvent(&Event{Level: INFO, Filename: "foo.go", MsgSimpleText: "by filename"}) - logger.Close() - - assert.Equal(t, []string{"bar\n"}, w1.GetLogs()) -} diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index f7955115e0..e229ee4c65 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -104,7 +104,7 @@ func TestRender_Images(t *testing.T) { test( "!["+title+"]("+url+")", - `

`+title+`

`) + `

`+title+`

`) test( "[["+title+"|"+url+"]]", @@ -115,7 +115,7 @@ func TestRender_Images(t *testing.T) { test( "!["+title+"]("+url+")", - `

`+title+`

`) + `

`+title+`

`) test( "[["+title+"|"+url+"]]", @@ -412,8 +412,8 @@ func TestRenderSiblingImages_Issue12925(t *testing.T) { testcase := `![image1](/image1) ![image2](/image2) ` - expected := `

image1
-image2

+ expected := `

image1
+image2

` res, err := markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase) require.NoError(t, err) @@ -845,10 +845,10 @@ mail@domain.com remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -872,10 +872,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -901,10 +901,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -930,10 +930,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -959,10 +959,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -988,10 +988,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -1018,10 +1018,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -1048,10 +1048,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -1078,10 +1078,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -1108,10 +1108,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -1139,10 +1139,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
@@ -1170,10 +1170,10 @@ space

remote link
local link
remote link
-local image
-local image
-local image
-remote image
+local image
+local image
+local image
+remote image


https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
diff --git a/modules/markup/markdown/transform_image.go b/modules/markup/markdown/transform_image.go index b86c9e3d41..0f9c69cae6 100644 --- a/modules/markup/markdown/transform_image.go +++ b/modules/markup/markdown/transform_image.go @@ -44,7 +44,6 @@ func (g *ASTTransformer) transformImage(ctx *markup.RenderContext, v *ast.Image) for _, attr := range v.Attributes() { image.SetAttribute(attr.Name, attr.Value) } - image.SetAttributeString("loading", []byte("lazy")) for child := v.FirstChild(); child != nil; { next := child.NextSibling() image.AppendChild(image, child) diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go index aacc2536bf..384dd1fe94 100644 --- a/modules/markup/sanitizer.go +++ b/modules/markup/sanitizer.go @@ -108,9 +108,6 @@ func createDefaultPolicy() *bluemonday.Policy { // Allow classes for emojis policy.AllowAttrs("class").Matching(regexp.MustCompile(`^emoji$`)).OnElements("img") - // Allow attributes for images - policy.AllowAttrs("loading").Matching(regexp.MustCompile(`^lazy$`)).OnElements("img") - // Allow icons, emojis, chroma syntax and keyword markup on span policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(emoji)|(language-math display)|(language-math inline))$|^([a-z][a-z0-9]{0,2})$|^` + keywordClass + `$`)).OnElements("span") policy.AllowAttrs("data-alias").Matching(regexp.MustCompile(`^[a-zA-Z0-9-_+]+$`)).OnElements("span") diff --git a/modules/markup/sanitizer_test.go b/modules/markup/sanitizer_test.go index a0faff0494..9805a34910 100644 --- a/modules/markup/sanitizer_test.go +++ b/modules/markup/sanitizer_test.go @@ -75,10 +75,6 @@ func Test_Sanitizer(t *testing.T) { // Emoji `THUMBS UP`, `THUMBS UP`, `THUMBS UP`, `THUMBS UP`, - - // Images lazy loading - `image1`, `image1`, - `image1`, `image1`, } for i := 0; i < len(testCases); i += 2 { diff --git a/modules/setting/log.go b/modules/setting/log.go index 6d069d0e9c..0747ac4dac 100644 --- a/modules/setting/log.go +++ b/modules/setting/log.go @@ -133,7 +133,6 @@ func loadLogModeByName(rootCfg ConfigProvider, loggerName, modeName string) (wri writerMode.StacktraceLevel = log.LevelFromString(ConfigInheritedKeyString(sec, "STACKTRACE_LEVEL", Log.StacktraceLogLevel.String())) writerMode.Prefix = ConfigInheritedKeyString(sec, "PREFIX") writerMode.Expression = ConfigInheritedKeyString(sec, "EXPRESSION") - writerMode.Exclusion = ConfigInheritedKeyString(sec, "EXCLUSION") // flags are updated and set below switch writerType { diff --git a/modules/setting/log_test.go b/modules/setting/log_test.go index 223bd68285..eda6dc36af 100644 --- a/modules/setting/log_test.go +++ b/modules/setting/log_test.go @@ -44,7 +44,6 @@ func TestLogConfigDefault(t *testing.T) { "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "stdflags", "Level": "info", "Prefix": "", @@ -84,7 +83,6 @@ logger.xorm.MODE = "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "stdflags", "Level": "info", "Prefix": "", @@ -123,7 +121,6 @@ MODE = console "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "stdflags", "Level": "info", "Prefix": "", @@ -171,7 +168,6 @@ ACCESS = file "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "stdflags", "Level": "info", "Prefix": "", @@ -195,7 +191,6 @@ ACCESS = file "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "none", "Level": "info", "Prefix": "", @@ -262,7 +257,6 @@ STDERR = true "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "stdflags", "Level": "warn", "Prefix": "", @@ -276,7 +270,6 @@ STDERR = true "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "stdflags", "Level": "error", "Prefix": "", @@ -294,7 +287,6 @@ STDERR = true "BufferLen": 10000, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "none", "Level": "warn", "Prefix": "", @@ -331,7 +323,6 @@ MODE = file LEVEL = error STACKTRACE_LEVEL = fatal EXPRESSION = filter -EXCLUSION = not FLAGS = medfile PREFIX = "[Prefix] " FILE_NAME = file-xxx.log @@ -350,7 +341,6 @@ COMPRESSION_LEVEL = 4 "BufferLen": 10, "Colorize": false, "Expression": "", - "Exclusion": "", "Flags": "stdflags", "Level": "info", "Prefix": "", @@ -370,7 +360,6 @@ COMPRESSION_LEVEL = 4 "BufferLen": 10, "Colorize": false, "Expression": "filter", - "Exclusion": "not", "Flags": "medfile", "Level": "error", "Prefix": "[Prefix] ", diff --git a/modules/structs/activitypub.go b/modules/structs/activitypub.go index 0cc257ff95..117eb0bed2 100644 --- a/modules/structs/activitypub.go +++ b/modules/structs/activitypub.go @@ -1,5 +1,4 @@ // Copyright 2022 The Gitea Authors. All rights reserved. -// Copyright 2024 The Forgejo Authors. All rights reserved. // SPDX-License-Identifier: MIT package structs @@ -8,15 +7,3 @@ package structs type ActivityPub struct { Context string `json:"@context"` } - -type APRemoteFollowOption struct { - Target string `json:"target"` -} - -type APPersonFollowItem struct { - ActorID string `json:"actor_id"` - Note string `json:"note"` - - OriginalURL string `json:"original_url"` - OriginalItem string `json:"original_item"` -} diff --git a/modules/structs/attachment.go b/modules/structs/attachment.go index 746f618cf0..0a3d4140c2 100644 --- a/modules/structs/attachment.go +++ b/modules/structs/attachment.go @@ -22,12 +22,6 @@ type Attachment struct { Type string `json:"type"` } -// WebAttachment the generic attachment with mime type -type WebAttachment struct { - *Attachment - MimeType string `json:"mime_type"` -} - // EditAttachmentOptions options for editing attachments // swagger:model type EditAttachmentOptions struct { diff --git a/modules/structs/hook.go b/modules/structs/hook.go index 11372ca6e1..5adcad0881 100644 --- a/modules/structs/hook.go +++ b/modules/structs/hook.go @@ -53,7 +53,8 @@ type CreateHookOption struct { BranchFilter string `json:"branch_filter" binding:"GlobPattern"` AuthorizationHeader string `json:"authorization_header"` // default: false - Active bool `json:"active"` + Active bool `json:"active"` + IsSystemWebhook bool `json:"is_system_webhook"` } // EditHookOption options when modify one hook diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go index 62e063213c..b75b061218 100644 --- a/modules/templates/util_render_test.go +++ b/modules/templates/util_render_test.go @@ -192,8 +192,8 @@ func TestRenderMarkdownToHtml(t *testing.T) { remote link local link remote link -local image -remote image +local image +remote image 88fc37a3c0...12fc37a3c0 (hash) diff --git a/modules/test/distant_federation_server_mock.go b/modules/test/distant_federation_server_mock.go index ea8a69e9b4..9bd908e2b9 100644 --- a/modules/test/distant_federation_server_mock.go +++ b/modules/test/distant_federation_server_mock.go @@ -10,79 +10,56 @@ import ( "net/http/httptest" "strings" "testing" - - "forgejo.org/modules/util" ) type FederationServerMockPerson struct { - ID int64 - Name string - PubKey string - PrivKey string + ID int64 + Name string + PubKey string } type FederationServerMockRepository struct { ID int64 } -type ApActorMock struct { - PrivKey string - PubKey string -} type FederationServerMock struct { - ApActor ApActorMock Persons []FederationServerMockPerson Repositories []FederationServerMockRepository LastPost string } func NewFederationServerMockPerson(id int64, name string) FederationServerMockPerson { - priv, pub, _ := util.GenerateKeyPair(3072) return FederationServerMockPerson{ - ID: id, - Name: name, - PubKey: pub, - PrivKey: priv, + ID: id, + Name: name, + PubKey: `"-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA18H5s7N6ItZUAh9tneII\nIuZdTTa3cZlLa/9ejWAHTkcp3WLW+/zbsumlMrWYfBy2/yTm56qasWt38iY4D6ul\n` + + `CPiwhAqX3REvVq8tM79a2CEqZn9ka6vuXoDgBg/sBf/BUWqf7orkjUXwk/U0Egjf\nk5jcurF4vqf1u+rlAHH37dvSBaDjNj6Qnj4OP12bjfaY/yvs7+jue/eNXFHjzN4E\n` + + `T2H4B/yeKTJ4UuAwTlLaNbZJul2baLlHelJPAsxiYaziVuV5P+IGWckY6RSerRaZ\nAkc4mmGGtjAyfN9aewe+lNVfwS7ElFx546PlLgdQgjmeSwLX8FWxbPE5A/PmaXCs\n` + + `nx+nou+3dD7NluULLtdd7K+2x02trObKXCAzmi5/Dc+yKTzpFqEz+hLNCz7TImP/\ncK//NV9Q+X67J9O27baH9R9ZF4zMw8rv2Pg0WLSw1z7lLXwlgIsDapeMCsrxkVO4\n` + + `LXX5AQ1xQNtlssnVoUBqBrvZsX2jUUKUocvZqMGuE4hfAgMBAAE=\n-----END PUBLIC KEY-----\n"`, } } -func (p *FederationServerMockPerson) KeyID(host string) string { - return fmt.Sprintf("%[1]v/api/v1/activitypub/user-id/%[2]v#main-key", host, p.ID) -} - func NewFederationServerMockRepository(id int64) FederationServerMockRepository { return FederationServerMockRepository{ ID: id, } } -func NewApActorMock() ApActorMock { - priv, pub, _ := util.GenerateKeyPair(1024) - return ApActorMock{ - PrivKey: priv, - PubKey: pub, - } -} - -func (u *ApActorMock) KeyID(host string) string { - return fmt.Sprintf("%[1]v/api/v1/activitypub/actor#main-key", host) -} - func (p FederationServerMockPerson) marshal(host string) string { return fmt.Sprintf(`{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1"],`+ - `"id":"http://%[1]v/api/v1/activitypub/user-id/%[2]v",`+ + `"id":"http://%[1]v/api/activitypub/user-id/%[2]v",`+ `"type":"Person",`+ `"icon":{"type":"Image","mediaType":"image/png","url":"http://%[1]v/avatars/1bb05d9a5f6675ed0272af9ea193063c"},`+ `"url":"http://%[1]v/%[2]v",`+ - `"inbox":"http://%[1]v/api/v1/activitypub/user-id/%[2]v/inbox",`+ - `"outbox":"http://%[1]v/api/v1/activitypub/user-id/%[2]v/outbox",`+ + `"inbox":"http://%[1]v/api/activitypub/user-id/%[2]v/inbox",`+ + `"outbox":"http://%[1]v/api/activitypub/user-id/%[2]v/outbox",`+ `"preferredUsername":"%[3]v",`+ - `"publicKey":{"id":"http://%[1]v/api/v1/activitypub/user-id/%[2]v#main-key",`+ - `"owner":"http://%[1]v/api/v1/activitypub/user-id/%[2]v",`+ - `"publicKeyPem":%[4]q}}`, host, p.ID, p.Name, p.PubKey) + `"publicKey":{"id":"http://%[1]v/api/activitypub/user-id/%[2]v#main-key",`+ + `"owner":"http://%[1]v/api/activitypub/user-id/%[2]v",`+ + `"publicKeyPem":%[4]v}}`, host, p.ID, p.Name, p.PubKey) } func NewFederationServerMock() *FederationServerMock { return &FederationServerMock{ - ApActor: NewApActorMock(), Persons: []FederationServerMockPerson{ NewFederationServerMockPerson(15, "stargoose1"), NewFederationServerMockPerson(30, "stargoose2"), @@ -94,18 +71,8 @@ func NewFederationServerMock() *FederationServerMock { } } -func (mock *FederationServerMock) recordLastPost(t *testing.T, req *http.Request) { - buf := new(strings.Builder) - _, err := io.Copy(buf, req.Body) - if err != nil { - t.Errorf("Error reading body: %q", err) - } - mock.LastPost = strings.ReplaceAll(buf.String(), req.Host, "DISTANT_FEDERATION_HOST") -} - func (mock *FederationServerMock) DistantServer(t *testing.T) *httptest.Server { federatedRoutes := http.NewServeMux() - federatedRoutes.HandleFunc("/.well-known/nodeinfo", func(res http.ResponseWriter, req *http.Request) { // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo @@ -120,28 +87,30 @@ func (mock *FederationServerMock) DistantServer(t *testing.T) *httptest.Server { `"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},`+ `"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`) }) - for _, person := range mock.Persons { federatedRoutes.HandleFunc(fmt.Sprintf("/api/v1/activitypub/user-id/%v", person.ID), func(res http.ResponseWriter, req *http.Request) { // curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/2 fmt.Fprint(res, person.marshal(req.Host)) }) - federatedRoutes.HandleFunc(fmt.Sprintf("POST /api/v1/activitypub/user-id/%v/inbox", person.ID), - func(res http.ResponseWriter, req *http.Request) { - mock.recordLastPost(t, req) - }) } - for _, repository := range mock.Repositories { - federatedRoutes.HandleFunc(fmt.Sprintf("POST /api/v1/activitypub/repository-id/%v/inbox", repository.ID), + federatedRoutes.HandleFunc(fmt.Sprintf("/api/v1/activitypub/repository-id/%v/inbox", repository.ID), func(res http.ResponseWriter, req *http.Request) { - mock.recordLastPost(t, req) + if req.Method != "POST" { + t.Errorf("POST expected at: %q", req.URL.EscapedPath()) + } + buf := new(strings.Builder) + _, err := io.Copy(buf, req.Body) + if err != nil { + t.Errorf("Error reading body: %q", err) + } + mock.LastPost = buf.String() }) } federatedRoutes.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) { - t.Errorf("Unhandled %v request: %q", req.Method, req.URL.EscapedPath()) + t.Errorf("Unhandled request: %q", req.URL.EscapedPath()) }) federatedSrv := httptest.NewServer(federatedRoutes) return federatedSrv diff --git a/modules/typesniffer/typesniffer.go b/modules/typesniffer/typesniffer.go index 8cb1513a88..262feb2b05 100644 --- a/modules/typesniffer/typesniffer.go +++ b/modules/typesniffer/typesniffer.go @@ -124,7 +124,7 @@ func (ct SniffedType) GetMimeType() string { } // DetectContentType extends http.DetectContentType with more content types. Defaults to text/unknown if input is empty. -func DetectContentType(data []byte, filename string) SniffedType { +func DetectContentType(data []byte) SniffedType { if len(data) == 0 { return SniffedType{"text/unknown"} } @@ -176,13 +176,6 @@ func DetectContentType(data []byte, filename string) SniffedType { } } - if ct == "application/octet-stream" && - filename != "" && - !strings.HasSuffix(strings.ToUpper(filename), ".LCOM") && - bytes.Contains(data, []byte("(DEFINE-FILE-INFO ")) { - ct = "text/vnd.interlisp" - } - // GLTF is unsupported by http.DetectContentType // hexdump -n 4 -C glTF.glb if bytes.HasPrefix(data, []byte("glTF")) { @@ -193,7 +186,7 @@ func DetectContentType(data []byte, filename string) SniffedType { } // DetectContentTypeFromReader guesses the content type contained in the reader. -func DetectContentTypeFromReader(r io.Reader, filename string) (SniffedType, error) { +func DetectContentTypeFromReader(r io.Reader) (SniffedType, error) { buf := make([]byte, sniffLen) n, err := util.ReadAtMost(r, buf) if err != nil { @@ -201,5 +194,5 @@ func DetectContentTypeFromReader(r io.Reader, filename string) (SniffedType, err } buf = buf[:n] - return DetectContentType(buf, filename), nil + return DetectContentType(buf), nil } diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index d2b7ed4f21..176d3658bb 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -16,63 +16,63 @@ import ( func TestDetectContentTypeLongerThanSniffLen(t *testing.T) { // Pre-condition: Shorter than sniffLen detects SVG. - assert.Equal(t, "image/svg+xml", DetectContentType([]byte(``), "").contentType) + assert.Equal(t, "image/svg+xml", DetectContentType([]byte(``)).contentType) // Longer than sniffLen detects something else. - assert.NotEqual(t, "image/svg+xml", DetectContentType([]byte(``), "").contentType) + assert.NotEqual(t, "image/svg+xml", DetectContentType([]byte(``)).contentType) } func TestIsTextFile(t *testing.T) { - assert.True(t, DetectContentType([]byte{}, "").IsText()) - assert.True(t, DetectContentType([]byte("lorem ipsum"), "").IsText()) + assert.True(t, DetectContentType([]byte{}).IsText()) + assert.True(t, DetectContentType([]byte("lorem ipsum")).IsText()) } func TestIsSvgImage(t *testing.T) { - assert.True(t, DetectContentType([]byte(""), "").IsSvgImage()) - assert.True(t, DetectContentType([]byte(" "), "").IsSvgImage()) - assert.True(t, DetectContentType([]byte(``), "").IsSvgImage()) - assert.True(t, DetectContentType([]byte(``), "").IsSvgImage()) + assert.True(t, DetectContentType([]byte("")).IsSvgImage()) + assert.True(t, DetectContentType([]byte(" ")).IsSvgImage()) + assert.True(t, DetectContentType([]byte(``)).IsSvgImage()) + assert.True(t, DetectContentType([]byte(``)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) // the DetectContentType should work for incomplete data, because only beginning bytes are used for detection - assert.True(t, DetectContentType([]byte(`....`), "").IsSvgImage()) + assert.True(t, DetectContentType([]byte(`....`)).IsSvgImage()) - assert.False(t, DetectContentType([]byte{}, "").IsSvgImage()) - assert.False(t, DetectContentType([]byte("svg"), "").IsSvgImage()) - assert.False(t, DetectContentType([]byte(""), "").IsSvgImage()) - assert.False(t, DetectContentType([]byte("text"), "").IsSvgImage()) - assert.False(t, DetectContentType([]byte(""), "").IsSvgImage()) - assert.False(t, DetectContentType([]byte(``), "").IsSvgImage()) + assert.False(t, DetectContentType([]byte{}).IsSvgImage()) + assert.False(t, DetectContentType([]byte("svg")).IsSvgImage()) + assert.False(t, DetectContentType([]byte("")).IsSvgImage()) + assert.False(t, DetectContentType([]byte("text")).IsSvgImage()) + assert.False(t, DetectContentType([]byte("")).IsSvgImage()) + assert.False(t, DetectContentType([]byte(``)).IsSvgImage()) assert.False(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.False(t, DetectContentType([]byte(` - `), "").IsSvgImage()) + `)).IsSvgImage()) assert.False(t, DetectContentType([]byte(` @@ -80,7 +80,7 @@ func TestIsSvgImage(t *testing.T) { -`), "").IsSvgImage()) +`)).IsSvgImage()) assert.False(t, DetectContentType([]byte(` -`), "").IsSvgImage()) - assert.False(t, DetectContentType([]byte(``), "").IsSvgImage()) - assert.False(t, DetectContentType([]byte(``), "").IsSvgImage()) +`)).IsSvgImage()) + assert.False(t, DetectContentType([]byte(``)).IsSvgImage()) + assert.False(t, DetectContentType([]byte(``)).IsSvgImage()) } func TestIsPDF(t *testing.T) { pdf, _ := base64.StdEncoding.DecodeString("JVBERi0xLjYKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nF3NPwsCMQwF8D2f4s2CNYk1baF0EHRwOwg4iJt/NsFb/PpevUE4Mjwe") - assert.True(t, DetectContentType(pdf, "").IsPDF()) - assert.False(t, DetectContentType([]byte("plain text"), "").IsPDF()) + assert.True(t, DetectContentType(pdf).IsPDF()) + assert.False(t, DetectContentType([]byte("plain text")).IsPDF()) } func TestIsVideo(t *testing.T) { mp4, _ := base64.StdEncoding.DecodeString("AAAAGGZ0eXBtcDQyAAAAAGlzb21tcDQyAAEI721vb3YAAABsbXZoZAAAAADaBlwX2gZcFwAAA+gA") - assert.True(t, DetectContentType(mp4, "").IsVideo()) - assert.False(t, DetectContentType([]byte("plain text"), "").IsVideo()) + assert.True(t, DetectContentType(mp4).IsVideo()) + assert.False(t, DetectContentType([]byte("plain text")).IsVideo()) } func TestIsAudio(t *testing.T) { mp3, _ := base64.StdEncoding.DecodeString("SUQzBAAAAAABAFRYWFgAAAASAAADbWFqb3JfYnJhbmQAbXA0MgBUWFhYAAAAEQAAA21pbm9yX3Zl") - assert.True(t, DetectContentType(mp3, "").IsAudio()) - assert.False(t, DetectContentType([]byte("plain text"), "").IsAudio()) + assert.True(t, DetectContentType(mp3).IsAudio()) + assert.False(t, DetectContentType([]byte("plain text")).IsAudio()) - assert.True(t, DetectContentType([]byte("ID3Toy\000"), "").IsAudio()) - assert.True(t, DetectContentType([]byte("ID3Toy\n====\t* hi 🌞, ..."), "").IsText()) // test ID3 tag for plain text - assert.True(t, DetectContentType([]byte("ID3Toy\n====\t* hi 🌞, ..."+"🌛"[0:2]), "").IsText()) // test ID3 tag with incomplete UTF8 char + assert.True(t, DetectContentType([]byte("ID3Toy\000")).IsAudio()) + assert.True(t, DetectContentType([]byte("ID3Toy\n====\t* hi 🌞, ...")).IsText()) // test ID3 tag for plain text + assert.True(t, DetectContentType([]byte("ID3Toy\n====\t* hi 🌞, ..."+"🌛"[0:2])).IsText()) // test ID3 tag with incomplete UTF8 char } func TestIsGLB(t *testing.T) { glb, _ := hex.DecodeString("676c5446") - assert.True(t, DetectContentType(glb, "").IsGLB()) - assert.True(t, DetectContentType(glb, "").Is3DModel()) - assert.False(t, DetectContentType([]byte("plain text"), "").IsGLB()) - assert.False(t, DetectContentType([]byte("plain text"), "").Is3DModel()) + assert.True(t, DetectContentType(glb).IsGLB()) + assert.True(t, DetectContentType(glb).Is3DModel()) + assert.False(t, DetectContentType([]byte("plain text")).IsGLB()) + assert.False(t, DetectContentType([]byte("plain text")).Is3DModel()) } func TestDetectContentTypeFromReader(t *testing.T) { mp3, _ := base64.StdEncoding.DecodeString("SUQzBAAAAAABAFRYWFgAAAASAAADbWFqb3JfYnJhbmQAbXA0MgBUWFhYAAAAEQAAA21pbm9yX3Zl") - st, err := DetectContentTypeFromReader(bytes.NewReader(mp3), "") + st, err := DetectContentTypeFromReader(bytes.NewReader(mp3)) require.NoError(t, err) assert.True(t, st.IsAudio()) } func TestDetectContentTypeOgg(t *testing.T) { oggAudio, _ := hex.DecodeString("4f67675300020000000000000000352f0000000000007dc39163011e01766f72626973000000000244ac0000000000000071020000000000b8014f6767530000") - st, err := DetectContentTypeFromReader(bytes.NewReader(oggAudio), "") + st, err := DetectContentTypeFromReader(bytes.NewReader(oggAudio)) require.NoError(t, err) assert.True(t, st.IsAudio()) oggVideo, _ := hex.DecodeString("4f676753000200000000000000007d9747ef000000009b59daf3012a807468656f7261030201001e00110001e000010e00020000001e00000001000001000001") - st, err = DetectContentTypeFromReader(bytes.NewReader(oggVideo), "") + st, err = DetectContentTypeFromReader(bytes.NewReader(oggVideo)) require.NoError(t, err) assert.True(t, st.IsVideo()) } @@ -148,7 +148,7 @@ func TestDetectContentTypeAvif(t *testing.T) { avifImage, err := hex.DecodeString("000000206674797061766966") require.NoError(t, err) - st, err := DetectContentTypeFromReader(bytes.NewReader(avifImage), "") + st, err := DetectContentTypeFromReader(bytes.NewReader(avifImage)) require.NoError(t, err) assert.True(t, st.IsImage()) @@ -158,24 +158,10 @@ func TestDetectContentTypeModelGLB(t *testing.T) { glb, err := hex.DecodeString("676c5446") require.NoError(t, err) - st, err := DetectContentTypeFromReader(bytes.NewReader(glb), "") + st, err := DetectContentTypeFromReader(bytes.NewReader(glb)) require.NoError(t, err) // print st for debugging assert.Equal(t, "model/gltf-binary", st.GetMimeType()) assert.True(t, st.IsGLB()) } - -func TestDetectInterlisp(t *testing.T) { - interlisp, err := base64.StdEncoding.DecodeString("ICAKKERFRklORS1GSUxFLUlORk8gHlBBQ0tBR0UgIklOVEVSTElTUCIgHlJFQURUQUJMRSAiSU5URVJMSVNQIiAeQkFTRSAxMCkKCgYB") - require.NoError(t, err) - st, err := DetectContentTypeFromReader(bytes.NewReader(interlisp), "test") - require.NoError(t, err) - assert.True(t, st.IsText()) - st, err = DetectContentTypeFromReader(bytes.NewReader(interlisp), "") - require.NoError(t, err) - assert.False(t, st.IsText()) - st, err = DetectContentTypeFromReader(bytes.NewReader(interlisp), "test.lcom") - require.NoError(t, err) - assert.False(t, st.IsText()) -} diff --git a/options/locale/locale_ar.ini b/options/locale/locale_ar.ini index 15d614e8bc..f4ac1a0e3d 100644 --- a/options/locale/locale_ar.ini +++ b/options/locale/locale_ar.ini @@ -699,7 +699,7 @@ issues.filter_milestone_all = كل الأهداف issues.unlock.notice_2 = - يمكنك دوما إقفال هذه المسألة من جديد في المستقبل. issues.num_participants_few = %d متحاور release.title = عنوان الإصدار -issues.closed_at = `أغلق هذه المسألة %s` +issues.closed_at = `أغلق هذه المسألة %[2]s` issues.lock.title = إقفال التحاور في هذه المسألة. issues.new.no_label = بلا تصنيف issues.filter_sort.mostforks = الأعلى اشتقاقا @@ -759,7 +759,7 @@ branch.renamed = غُيّر اسم الفرع %s إلى %s. delete_preexisting = احذف الملفات الموجودة سابقا branch.included_desc = هذا الفرع جزء من الفرع المبدئي trust_model_helper_collaborator_committer = مشترك+مودع: ثق بتوقيعات المشتركين التي تطابق المودع -issues.reopened_at = `أعاد فتح هذه المسألة %s` +issues.reopened_at = `أعاد فتح هذه المسألة %[2]s` issues.action_milestone = هدف issues.new.assignees = المكلَّفون release.tag_name_protected = اسم الوسم محمي. @@ -1166,7 +1166,7 @@ pulls.status_checking = في انتظار بعض الفحوص pulls.status_checks_failure = بعض الفحوص فشلت pulls.status_checks_success = جميع الفحوص ناجحة pulls.status_checks_warning = بعض الفحوص تعطي تحذيرات -pulls.commit_ref_at = `أشار إلى طلب الدمج من إيداع %s` +pulls.commit_ref_at = `أشار إلى طلب الدمج من إيداع %[2]s` pulls.cmd_instruction_hint = `أظهر شرح استخدام سطر الأوامر.` pulls.cmd_instruction_checkout_title = اسحب pulls.cmd_instruction_checkout_desc = من مستودع مشروعك، اسحب (check out) فرعا جديدا واختبر التغييرات. @@ -1257,8 +1257,8 @@ pulls.status_checks_details = تفاصيل pulls.status_checks_hide_all = أخفِ كل الفحوص pulls.status_checks_show_all = أظهر كل الفحوص pulls.close = أغلق طلب الدمج -pulls.closed_at = `أغلق طلب الدمج %s` -pulls.reopened_at = `أعاد فتح طلب الدمج %s` +pulls.closed_at = `أغلق طلب الدمج %[2]s` +pulls.reopened_at = `أعاد فتح طلب الدمج %[2]s` milestones.title = العنوان milestones.desc = الوصف milestones.edit = عدّل الهدف @@ -1302,11 +1302,11 @@ issues.closed_by_fake = من %[2]s أُغلقت %[1]s issues.num_comments_1 = %d تعليق issues.num_comments = %d تعليقا issues.commented_at = `علّق %s` -issues.commit_ref_at = `أشار إلى هذه المسألة من إيداع %s` -issues.ref_issue_from = `أشار إلى هذه المسألة %[3]s %[1]s` -issues.ref_pull_from = `أشار إلى هذا الطلب %[3]s %[1]s` -issues.ref_closing_from = `أشار إلى طلب دمج %[3]s سيغلق هذه المسألة %[1]s` -issues.ref_reopening_from = `أشار إلى طلب دمج %[3]s سيعيد فتح هذه المسألة %[1]s` +issues.commit_ref_at = `أشار إلى هذه المسألة من إيداع %[2]s` +issues.ref_issue_from = `أشار إلى هذه المسألة %[4]s %[2]s` +issues.ref_pull_from = `أشار إلى هذا الطلب %[4]s %[2]s` +issues.ref_closing_from = `أشار إلى طلب دمج %[4]s سيغلق هذه المسألة %[2]s` +issues.ref_reopening_from = `أشار إلى طلب دمج %[4]s سيعيد فتح هذه المسألة %[2]s` issues.ref_closed_from = `أغلق هذه المسألة %[4]s %[2]s` issues.ref_reopened_from = `أعاد فتح هذه المسألة %[4]s %[2]s` issues.reference_issue.body = المحتوى diff --git a/options/locale/locale_bg.ini b/options/locale/locale_bg.ini index 1b9767f674..abce4f1133 100644 --- a/options/locale/locale_bg.ini +++ b/options/locale/locale_bg.ini @@ -749,7 +749,7 @@ settings.admin_settings = Администраторски настройки issues.role.owner = Притежател settings.transfer.title = Прехвърляне на притежанието issues.author = Автор -issues.closed_at = `затвори тази задача %s` +issues.closed_at = `затвори тази задача %[2]s` settings.collaborator_deletion_desc = Премахването на сътрудник ще отнеме достъпа му до това хранилище. Продължаване? commits.message = Съобщение issues.due_date_not_set = Няма зададен краен срок. @@ -773,9 +773,9 @@ issues.filter_type.all_issues = Всички задачи issues.filter_poster_no_select = Всички автори issues.opened_by = отворена %[1]s от %[3]s issues.action_open = Отваряне -pulls.closed_at = `затвори тази заявка за сливане %s` -pulls.reopened_at = `отвори наново тази заявка за сливане %s` -issues.reopened_at = `отвори наново тази задача %s` +pulls.closed_at = `затвори тази заявка за сливане %[2]s` +pulls.reopened_at = `отвори наново тази заявка за сливане %[2]s` +issues.reopened_at = `отвори наново тази задача %[2]s` projects.column.edit = Редактиране на колоната issues.close = Затваряне на задачата issues.ref_reopened_from = `отвори наново тази задача %[4]s %[2]s` @@ -1205,7 +1205,7 @@ issues.dependency.cancel = Отказ issues.dependency.add_error_dep_exists = Зависимостта вече съществува. issues.dependency.add_error_dep_not_exist = Зависимостта не съществува. issues.remove_ref_at = `премахна препратката %s %s` -issues.ref_pull_from = `спомена тази заявка за сливане %[3]s %[1]s` +issues.ref_pull_from = `спомена тази заявка за сливане %[4]s %[2]s` issues.dependency.pr_no_dependencies = Няма зададени зависимости. issues.dependency.remove_info = Премахване на тази зависимост issues.dependency.removed_dependency = `премахна зависимостта %s` @@ -1230,11 +1230,11 @@ issues.dependency.title = Зависимости issues.dependency.issue_no_dependencies = Няма зададени зависимости. issues.dependency.pr_close_blocked = Трябва да затворите всички задачи, блокиращи тази заявка за сливане, преди да можете да я слеете. issues.dependency.pr_close_blocks = Тази заявка за сливане блокира затварянето на следните задачи -issues.ref_issue_from = `спомена тази задача %[3]s %[1]s` -issues.commit_ref_at = `спомена тази задача в подаване %s` +issues.ref_issue_from = `спомена тази задача %[4]s %[2]s` +issues.commit_ref_at = `спомена тази задача в подаване %[2]s` issues.add_ref_at = `добави препратка %s %s` pulls.merged_info_text = Клонът %s вече може да бъде изтрит. -pulls.commit_ref_at = `спомена тази заявка за сливане в подаване %s` +pulls.commit_ref_at = `спомена тази заявка за сливане в подаване %[2]s` issues.change_ref_at = `промени препратката от %s на %s %s` diff.review.reject = Поискване на промени diff.bin_not_shown = Двоичният файл не е показан. @@ -1299,9 +1299,9 @@ branch.create_new_branch = Създаване на клон от клон: pulls.status_checks_show_all = Показване на всички проверки size_format = %[1]s: %[2]s; %[3]s: %[4]s pulls.filter_changes_by_commit = Филтриране по подаване -issues.ref_closing_from = `спомена тази задача в заявка за сливане %[3]s, която ще я затвори, %[1]s` +issues.ref_closing_from = `спомена тази задача в заявка за сливане %[4]s, която ще я затвори, %[2]s` issues.ref_from = `от %[1]s` -issues.ref_reopening_from = `спомена тази задача в заявка за сливане %[3]s, която ще я отвори наново , %[1]s` +issues.ref_reopening_from = `спомена тази задача в заявка за сливане %[4]s, която ще я отвори наново , %[2]s` issues.draft_title = Чернова pulls.reopen_to_merge = Моля, отворете наново тази заявка за сливане, за да извършите сливане. pulls.cant_reopen_deleted_branch = Тази заявка за сливане не може да бъде отворена наново, защото клонът е изтрит. diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 168965a740..9448dd8e7e 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -1063,7 +1063,7 @@ language.localization_project = Pomozte nám s překladem Forgejo do vašeho jaz user_block_yourself = Nemůžete zablokovat sami sebe. pronouns_custom_label = Vlastní zájmena change_username_redirect_prompt.with_cooldown.few = Staré uživatelské jméno bude dostupné ostatním po %[1]d dnech. Do té doby budete moci své staré uživatelské jméno znovu získat. -change_username_redirect_prompt.with_cooldown.one = Staré uživatelské jméno bude dostupné ostatním po %[1]d dnu. Do té doby budete moci své staré uživatelské jméno znovu získat. +change_username_redirect_prompt.with_cooldown.one = Staré uživatelské jméno bude dostupné ostatním po %[1]d dni. Do té doby budete moci své staré uživatelské jméno znovu získat. keep_pronouns_private = Zobrazovat zájmena pouze přihlášeným uživatelům keep_pronouns_private.description = Toto nastavení skryje vaše zájmena před návštěvníky, kteří nejsou přihlášeni. quota = Kvóta @@ -1579,7 +1579,7 @@ issues.remove_ref_at=`odstranil/a referenci %s %s` issues.add_ref_at=`přidal/a referenci %s %s` issues.delete_branch_at=`odstranil/a větev %s %s` issues.filter_label=Štítek -issues.filter_label_exclude=Chcete-li vyloučit štítky, použijte Alt + kliknutí +issues.filter_label_exclude=`Chcete-li vyloučit štítky, použijte alt + click/enter` issues.filter_label_no_select=Všechny štítky issues.filter_label_select_no_label=Bez štítku issues.filter_milestone=Milník @@ -1633,13 +1633,13 @@ issues.opened_by_fake=otevřeno %[1]s uživatelem %[2]s issues.closed_by_fake=od %[2]s byl uzavřen %[1]s issues.previous=Předchozí issues.next=Další -issues.open_title=Otevřené -issues.closed_title=Uzavřené +issues.open_title=Otevřeno +issues.closed_title=Uzavřeno issues.draft_title=Koncept issues.num_comments_1=%d komentář issues.num_comments=%d komentářů issues.commented_at=`okomentoval/a %s` -issues.delete_comment_confirm=Opravdu chcete smazat tento komentář? +issues.delete_comment_confirm=Jste si jist, že chcete smazat tento komentář? issues.context.copy_link=Kopírovat odkaz issues.context.quote_reply=Citovat odpověď issues.context.reference_issue=Odkázat v novém problému @@ -1653,13 +1653,13 @@ issues.close_comment_issue=Zavřít s komentářem issues.reopen_issue=Znovu otevřít issues.reopen_comment_issue=Znovu otevřít s komentářem issues.create_comment=Komentovat -issues.closed_at=`uzavřel/a tento problém %s` -issues.reopened_at=`znovu otevřel/a tento problém %s` -issues.commit_ref_at=`odkázal/a na tento problém z revize %s` -issues.ref_issue_from=`odkázal/a na tento problém %[3]s %[1]s` -issues.ref_pull_from=`odkázal/a na tuto žádost o sloučení %[3]s %[1]s` -issues.ref_closing_from=`odkázal/a na tento problém ze žádosti o sloučení %[3]s, která jej uzavře, %[1]s` -issues.ref_reopening_from=`odkázal/a na tento problém ze žádosti o sloučení %[3]s, která jej znovu otevře, %[1]s` +issues.closed_at=`uzavřel/a tento problém %[2]s` +issues.reopened_at=`znovu otevřel/a tento problém %[2]s` +issues.commit_ref_at=`odkázal/a na tento problém z revize %[2]s` +issues.ref_issue_from=`odkázal/a na tento problém %[4]s %[2]s` +issues.ref_pull_from=`odkázal/a na tuto žádost o sloučení %[4]s %[2]s` +issues.ref_closing_from=`odkazoval/a na tento problém ze žádosti o sloučení %[4]s, která jej uzavře, %[2]s` +issues.ref_reopening_from=`odkazoval/a na tento problém ze žádosti o sloučení %[4]s, která jej znovu otevře, %[2]s` issues.ref_closed_from=`uzavřel/a tento problém %[4]s %[2]s` issues.ref_reopened_from=`znovu otevřel/a tento problém %[4]s %[2]s` issues.ref_from=`z %[1]s` @@ -1966,8 +1966,8 @@ pulls.update_branch_success=Aktualizace větve byla úspěšná pulls.update_not_allowed=Nemáte oprávnění aktualizovat větev pulls.outdated_with_base_branch=Tato větev je zastaralá oproti základní větvi pulls.close=Zavřít žádost o sloučení -pulls.closed_at=`uzavřel/a tuto žádost o sloučení %s` -pulls.reopened_at=`znovu otevřel/a tuto žádost o sloučení %s` +pulls.closed_at=`uzavřel/a tuto žádost o sloučení %[2]s` +pulls.reopened_at=`znovu otevřel/a tuto žádost o sloučení %[2]s` pulls.cmd_instruction_hint=Zobrazit instrukce příkazové řádky pulls.cmd_instruction_checkout_desc=Z vašeho repositáře projektu se podívejte na novou větev a vyzkoušejte změny. pulls.cmd_instruction_merge_title=Sloučit @@ -2758,7 +2758,7 @@ settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning = Tuto ak settings.new_owner_blocked_doer = Nový majitel vás zablokoval. settings.mirror_settings.pushed_repository = Odeslaný repozitář settings.add_collaborator_blocked_our = Nepodařilo se přidat spolupracovníka, jelikož byl zablokován majitelem repozitáře. -pulls.commit_ref_at = `odkázal/a na tuto žádost o sloučení z revize %s` +pulls.commit_ref_at = `se odkázal/a na tuto žádost o sloučení z revize %[2]s` settings.wiki_rename_branch_main = Normalizovat název větve wiki settings.wiki_rename_branch_main_desc = Přejmenovat větev interně používanou pro wiki na „%s“. Tato změna je trvalá a nelze ji vrátit. pulls.fast_forward_only_merge_pull_request = Pouze zrychlené @@ -3058,7 +3058,7 @@ teams.invite.by=Pozvání od %s teams.invite.description=Pro připojení k týmu klikněte na tlačítko níže. follow_blocked_user = Tuto organizaci nemůžete sledovat, protože jste v ní zablokováni. open_dashboard = Otevřít nástěnku -settings.change_orgname_redirect_prompt.with_cooldown.one = Starý název organizace bude dostupný ostatním po %[1]d dnu. Do té doby budete moci staré jméno znovu získat. +settings.change_orgname_redirect_prompt.with_cooldown.one = Starý název organizace bude dostupný ostatním po %[1]d dni. Do té doby budete moci staré jméno znovu získat. settings.change_orgname_redirect_prompt.with_cooldown.few = Starý název organizace bude dostupný ostatním po %[1]d dnech. Do té doby budete moci starý název znovu získat. [admin] diff --git a/options/locale/locale_da.ini b/options/locale/locale_da.ini index c82779ab60..ea22f49e77 100644 --- a/options/locale/locale_da.ini +++ b/options/locale/locale_da.ini @@ -1520,15 +1520,15 @@ issues.add_labels = tilføjede %s etiketterne %s issues.add_remove_labels = tilføjede %s og fjernede %s etiketter %s issues.add_milestone_at = `føjede dette til %s milepælen %s` issues.add_project_at = `føjede dette til %s- projektet %s` -issues.ref_reopening_from = `henviste til dette problem fra en pull-anmodning %[3]s, der vil genåbne den, %[1]s` +issues.ref_reopening_from = `henviste til dette problem fra en pull-anmodning %[4]s, der vil genåbne den, %[2]s` issues.ref_closed_from = `lukkede dette problem %[4]s %[2 ]s` issues.ref_reopened_from = `genåbnede dette problem %[4]s %[2 ]s` issues.ref_from = `fra %[1]s` issues.author = Forfatter -issues.commit_ref_at = `henviste til dette problem fra en commit %s` -issues.ref_issue_from = `henviste til dette problem %[3]s %[2 ]s` -issues.ref_pull_from = `henviste til denne pull-anmodning %[3]s %[1]s` -issues.ref_closing_from = `henviste til dette problem fra en pull-anmodning %[3]s, der vil lukke det, %[1]s` +issues.commit_ref_at = `henviste til dette problem fra en commit %[2]s` +issues.ref_issue_from = `henviste til dette problem %[4]s %[2 ]s` +issues.ref_pull_from = `henviste til denne pull-anmodning %[4]s %[ 2]s` +issues.ref_closing_from = `henviste til dette problem fra en pull-anmodning %[4]s, der vil lukke det, %[2]s` issues.author.tooltip.issue = Denne bruger er forfatteren til dette problem. issues.author.tooltip.pr = Denne bruger er forfatteren af denne pull-anmodning. issues.role.owner = Ejer @@ -1564,8 +1564,8 @@ issues.reaction.alt_add = Tilføj %[1]s reaktion til kommentar. issues.context.menu = Kommentar menu issues.reopen_comment_issue = Genåbner med kommentar issues.create_comment = Kommentar -issues.closed_at = `lukkede dette problem %s` -issues.reopened_at = `genåbnede dette problem %s` +issues.closed_at = `lukkede dette problem %[2]s` +issues.reopened_at = `genåbnede dette problem %[2]s` issues.remove_label = fjernede %s etiketten %s issues.remove_labels = fjernede %s etiketterne %s issues.change_project_at = `modificerede projektet fra %s til %s %s` @@ -1911,10 +1911,10 @@ pulls.editable_explanation = Denne pull-anmodning tillader redigeringer fra vedl pulls.auto_merge_button_when_succeed = (Når kontroller lykkes) pulls.status_checks_requested = Påkrævet pulls.close = Luk pull anmodning -pulls.commit_ref_at = `henviste til denne pull-anmodning fra en commit %s` +pulls.commit_ref_at = `henviste til denne pull-anmodning fra en commit %[2]s` pulls.cmd_instruction_hint = Se instruktionerne på kommandolinjen -pulls.reopened_at = `genåbnede denne pull-anmodning %s` -pulls.closed_at = `lukkede denne pull-anmodning %s` +pulls.reopened_at = `genåbnede denne pull-anmodning %[2]s` +pulls.closed_at = `lukkede denne pull-anmodning %[2]s` pulls.cmd_instruction_checkout_desc = Fra dit projektdepot, tjek en ny gren og test ændringerne. pulls.editable = Redigerbar pulls.made_using_agit = AGit diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index f8bfc9258a..829912b3cc 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -1577,7 +1577,7 @@ issues.remove_ref_at=`hat die Referenz %s %s entfernt` issues.add_ref_at=`hat die Referenz %s %s hinzugefügt` issues.delete_branch_at=`löschte den Branch %s %s` issues.filter_label=Label -issues.filter_label_exclude=`Verwende Alt + Klick/Enter, um Labels auszuschließen` +issues.filter_label_exclude=`Alt + Klick/Enter verwenden, um Labels auszuschließen` issues.filter_label_no_select=Alle Labels issues.filter_label_select_no_label=Kein Label issues.filter_milestone=Meilenstein @@ -1651,13 +1651,13 @@ issues.close_comment_issue=Mit Kommentar schließen issues.reopen_issue=Wieder öffnen issues.reopen_comment_issue=Mit Kommentar wieder öffnen issues.create_comment=Kommentieren -issues.closed_at=`hat dieses Issue %s geschlossen` -issues.reopened_at=`hat dieses Issue %s wieder geöffnet` -issues.commit_ref_at=`hat dieses Issue %s aus einem Commit referenziert` -issues.ref_issue_from=`hat %[1]s auf dieses Issue verwiesen %[3]s` -issues.ref_pull_from=`referenzierte diesen Pull-Request %[3]s %[1]s` -issues.ref_closing_from=`referenzierte dieses Issue aus einem Pull-Request %[3]s der es schließen wird, %[1]s` -issues.ref_reopening_from=`referenzierte dieses Issue aus einem Pull-Request %[3]s der es wieder öffnen wird, %[1]s` +issues.closed_at=`hat diesen Issue %[2]s geschlossen` +issues.reopened_at=`hat dieses Issue %[2]s wieder geöffnet` +issues.commit_ref_at=`hat dieses Issue %[2]s aus einem Commit referenziert` +issues.ref_issue_from=`hat %[2]s auf dieses Issue verwiesen %[4]s` +issues.ref_pull_from=`hat %[2]s auf diesen Pull-Request verwiesen %[4]s` +issues.ref_closing_from=`hat %[2]s in einem Pull-Request %[4]s auf dieses Issue verwiesen, welcher es schließen wird` +issues.ref_reopening_from=`hat %[2]s in einem Pull-Request %[4]s auf dieses Issue verwiesen, welcher es erneut öffnen wird` issues.ref_closed_from=`hat dieses Issue %[4]s geschlossen %[2]s` issues.ref_reopened_from=`hat dieses Issue %[4]s %[2]s wieder geöffnet` issues.ref_from=`von %[1]s` @@ -1962,8 +1962,8 @@ pulls.update_branch_success=Branch-Aktualisierung erfolgreich pulls.update_not_allowed=Du hast keine Berechtigung, den Branch zu updaten 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` -pulls.reopened_at=`hat diesen Pull-Request %s wieder geöffnet` +pulls.closed_at=`hat diesen Pull-Request %[2]s geschlossen` +pulls.reopened_at=`hat diesen Pull-Request %[2]s wieder geöffnet` pulls.clear_merge_message=Merge-Nachricht löschen pulls.clear_merge_message_hint=Das Löschen der Merge-Nachricht wird nur den Inhalt der Commit-Nachricht entfernen und generierte Git-Trailer wie „Co-Authored-By …“ erhalten. @@ -2767,7 +2767,7 @@ 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.ignore_stale_approvals = Abgestandene Genehmigungen ignorieren settings.ignore_stale_approvals_desc = Genehmigungen, welche für ältere Commits gemacht wurden (abgestandene Reviews), nicht in die Gesamtzahl der Genehmigung des PRs mitzählen. Irrelevant, falls abgestandene Reviews bereits verworfen werden. -pulls.commit_ref_at = `referenzierte diesen Pull-Request aus einem Commit %s` +pulls.commit_ref_at = `hat sich auf diesen Pull-Request von einem Commit %[2]s bezogen` pulls.fast_forward_only_merge_pull_request = Nur Fast-forward pulls.cmd_instruction_checkout_desc = Checke einen neuen Branch aus deinem Projekt-Repository aus und teste die Änderungen. pulls.cmd_instruction_merge_title = Zusammenführen @@ -3061,8 +3061,8 @@ teams.invite.by=Von %s eingeladen teams.invite.description=Bitte klicke auf die folgende Schaltfläche, um dem Team beizutreten. follow_blocked_user = Du kannst dieser Organisation nicht folgen, weil diese Organisation dich blockiert hat. open_dashboard = Übersicht öffnen -settings.change_orgname_redirect_prompt.with_cooldown.one = Der alte Organisationsname ist nach einer Schutzzeit von einem Tag wieder für alle verfügbar. Du kannst den alten Namen während dieser Schutzzeit erneut beanspruchen. -settings.change_orgname_redirect_prompt.with_cooldown.few = Der alte Organisationsname ist nach einer Schutzzeit von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Namen während dieser Schutzzeit erneut beanspruchen. +settings.change_orgname_redirect_prompt.with_cooldown.one = Der alte Organisationsname ist nach einer Abkühldauer von einem Tag wieder für alle verfügbar. Du kannst den alten Namen während dieser Abkühldauer erneut beanspruchen. +settings.change_orgname_redirect_prompt.with_cooldown.few = Der alte Organisationsname ist nach einer Abkühldauer von %[1]d Tagen wieder für alle verfügbar. Du kannst den alten Namen während dieser Abkühldauer erneut beanspruchen. [admin] dashboard=Übersicht diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index 398a0d9ce4..29085aebf1 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -1626,13 +1626,13 @@ issues.close_comment_issue=Αποστολή σχολίου και κλείσιμ issues.reopen_issue=Ανοίξτε ξανά issues.reopen_comment_issue=Αποστολή σχολίου και επανάνοιγμα ζητήματος issues.create_comment=Προσθήκη Σχολίου -issues.closed_at=`αυτό το ζήτημα έκλεισε %s` -issues.reopened_at=`ξανά άνοιξε αυτό το ζήτημα %s` -issues.commit_ref_at=`αναφορά σε αυτό το ζήτημα από την παραπομπή %s` -issues.ref_issue_from=`αναφέρθηκε σε αυτό το ζήτημα %[3]s %[1]s` -issues.ref_pull_from=`αναφέρθηκε σε αυτό το pull request %[3]s %[1]s` -issues.ref_closing_from=`ανέφερε αυτό το ζήτημα σε ένα pull request %[3]s που στοχεύει να κλείσει το ζήτημα %[1]s` -issues.ref_reopening_from=`αναφέρθηκε σε αυτό το ζήτημα σε ένα pull request %[3]s που θα ξαναανοίξει αυτό το ζήτημα %[1]s` +issues.closed_at=`αυτό το ζήτημα έκλεισε %[2]s` +issues.reopened_at=`ξανά άνοιξε αυτό το ζήτημα %[2]s` +issues.commit_ref_at=`αναφορά σε αυτό το ζήτημα από την παραπομπή %[2]s` +issues.ref_issue_from=`αναφέρθηκε σε αυτό το ζήτημα %[4]s %[2]s` +issues.ref_pull_from=`αναφέρθηκε σε αυτό το pull request %[4]s %[2]s` +issues.ref_closing_from=`ανέφερε αυτό το ζήτημα σε ένα pull request %[4]s που στοχεύει να κλείσει το ζήτημα %[2]s` +issues.ref_reopening_from=`αναφέρθηκε σε αυτό το ζήτημα σε ένα pull request %[4]s που θα ξαναανοίξει αυτό το ζήτημα %[2]s` issues.ref_closed_from=`έκλεισε αυτό το ζήτημα %[4]s %[2]s` issues.ref_reopened_from=`άνοιξε ξανά αυτό το ζήτημα %[4]s %[2]s` issues.ref_from=`από %[1]s` @@ -1939,8 +1939,8 @@ pulls.update_branch_success=Η ενημέρωση του κλάδου ήταν pulls.update_not_allowed=Δεν επιτρέπεται να ενημερώσετε τον κλάδο pulls.outdated_with_base_branch=Αυτός ο κλάδος δεν είναι ενημερωμένος με τον βασικό κλάδο pulls.close=Κλείσιμο pull request -pulls.closed_at=`έκλεισε αυτό το pull request %s` -pulls.reopened_at=`άνοιξε ξανά αυτό το pull request %s` +pulls.closed_at=`έκλεισε αυτό το pull request %[2]s` +pulls.reopened_at=`άνοιξε ξανά αυτό το pull request %[2]s` pulls.cmd_instruction_hint=Προβολή οδηγιών γραμμής εντολών pulls.cmd_instruction_checkout_title=Έλεγχος pulls.cmd_instruction_checkout_desc=Από το repository του έργου σας, ελέγξτε έναν νέο κλάδο και δοκιμάστε τις αλλαγές. @@ -2720,7 +2720,7 @@ settings.new_owner_blocked_doer = Ο νέος κάτοχος του αποθετ settings.enter_repo_name = Γράψτε το όνομα του κατόχου και του αποθετηρίου ακριβώς όπως το βλέπετε: settings.confirmation_string = Κείμενο επιβεβαίωσης settings.units.overview = Επισκόπηση -pulls.commit_ref_at = `ανέφερε το pull request στο commit %s` +pulls.commit_ref_at = `ανέφερε το pull request στο commit %[2]s` contributors.contribution_type.filter_label = Είδος συνεισφοράς: settings.wiki_rename_branch_main_notices_1 = Αυτή η ενέργεια ΔΕΝ αναιρείται. activity.navbar.contributors = Συνεισφέροντες diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index bdafba93b4..f912409cc9 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -1648,13 +1648,13 @@ issues.close_comment_issue=Cerrar con comentario issues.reopen_issue=Reabrir issues.reopen_comment_issue=Reabrir con comentario issues.create_comment=Comentar -issues.closed_at=`cerró esta incidencia %s` -issues.reopened_at=`reabrió esta incidencia %s` -issues.commit_ref_at=`referenció esta incidencia en un commit %s` -issues.ref_issue_from=`referenció esta incidencia %[3]s %[1]s` -issues.ref_pull_from=`referenció este pull request %[3]s %[1]s` -issues.ref_closing_from=`hizo referencia a esta incidencia desde un pull request %[3]s que lo cerrará , %[1]s` -issues.ref_reopening_from=`hizo referencia a esta incidencia desde un pull request %[3]s que lo reabrirá, %[1]s` +issues.closed_at=`cerró esta incidencia %[2]s` +issues.reopened_at=`reabrió esta incidencia %[2]s` +issues.commit_ref_at=`referenció esta incidencia en un commit %[2]s` +issues.ref_issue_from=`referenció esta incidencia %[4]s %[2]s` +issues.ref_pull_from=`referenció este pull request %[4]s %[2]s` +issues.ref_closing_from=`hizo referencia a esta incidencia desde un pull request %[4]s que lo cerrará , %[2]s` +issues.ref_reopening_from=`hizo referencia a esta incidencia desde un pull request %[4]s que lo reabrirá, %[2]s` issues.ref_closed_from=`cerró esta incidencia %[4]s %[2]s` issues.ref_reopened_from=`reabrió esta incidencia %[4]s %[2]s` issues.ref_from=`de %[1]s` @@ -1959,8 +1959,8 @@ pulls.update_branch_success=La actualización de la rama ha finalizado correctam pulls.update_not_allowed=No tiene permisos para actualizar esta rama pulls.outdated_with_base_branch=Esta rama está desactualizada con la rama base pulls.close=Cerrar pull request -pulls.closed_at=`cerró este pull request %s` -pulls.reopened_at=`reabrió este pull request %s` +pulls.closed_at=`cerró este pull request %[2]s` +pulls.reopened_at=`reabrió este pull request %[2]s` pulls.clear_merge_message=Borrar mensaje de fusión pulls.clear_merge_message_hint=Limpiar el mensaje de fusión solo eliminará el contenido del mensaje de commit y mantendrá frases generadas como "Co-Autorizado por …". @@ -2789,7 +2789,7 @@ pulls.status_checks_hide_all = Ocultar todas las verificaciones settings.federation_not_enabled = La federación no está habilitada en tu instancia. wiki.search = Buscar en wiki pulls.status_checks_show_all = Mostrar todas las verificaciones -pulls.commit_ref_at = `hizo referencia a este pull request desde un commit %s` +pulls.commit_ref_at = `hizo referencia a este pull request desde un commit %[2]s` pulls.cmd_instruction_merge_title = Fusionar contributors.contribution_type.deletions = Eliminaciones contributors.contribution_type.filter_label = Tipo de contribución: diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index dae0695495..804b48b2b2 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -1250,13 +1250,13 @@ issues.close_comment_issue=ثبت دیدگاه و بستن issues.reopen_issue=بازگشایی issues.reopen_comment_issue=ثبت دیدگاه و بازگشایی issues.create_comment=دیدگاه -issues.closed_at=`%s این موضوع را بست` -issues.reopened_at=`%s این موضوع را دوباره باز کرد` -issues.commit_ref_at=`ارجاع این مسئله به کامیت %s` -issues.ref_issue_from=` ارجاعات این مسائله %[3] %[1]s` -issues.ref_pull_from=` ارجاعات این تقاضای ادغام %[4] %[1]s` -issues.ref_closing_from=` ارجاعات این تقاضای واکشی %[4] %[1]s` -issues.ref_reopening_from=` تقاضای واکشی ارجاع شده %[3]sکه مسائله بازگشایی خواهد کرد %[2] ` +issues.closed_at=`%[2]s این موضوع را بست` +issues.reopened_at=`%[2]s این موضوع را دوباره باز کرد` +issues.commit_ref_at=`ارجاع این مسئله به کامیت %[2]s` +issues.ref_issue_from=` ارجاعات این مسائله %[4] %[2]s` +issues.ref_pull_from=` ارجاعات این تقاضای ادغام %[4] %[2]s` +issues.ref_closing_from=` ارجاعات این تقاضای واکشی %[4] %[2]s` +issues.ref_reopening_from=` تقاضای واکشی ارجاع شده %[4] که مسائله بازگشایی خواهد کرد %[2] ` issues.ref_closed_from=` بسته شده این مسائله %[4] %[2]s` issues.ref_reopened_from=` بازگشایی این مسائله %[4] %[2]s` issues.ref_from=`از %[1]` @@ -1493,8 +1493,8 @@ pulls.update_branch_rebase=بروزآوری شاخه با بازسازی مجد pulls.update_branch_success=شاخه به موفقیت بروز شد pulls.update_not_allowed=شما اجازه بروزرسانی شاخه را ندارید pulls.outdated_with_base_branch=این شاخه با شاخه پایه منسوخ شده است -pulls.closed_at=`این درخواست pull بسته شده %s` -pulls.reopened_at=`این درخواست pull را بازگشایی کرد %s` +pulls.closed_at=`این درخواست pull بسته شده %[2]s` +pulls.reopened_at=`این درخواست pull را بازگشایی کرد %[2]s` diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini index efd8a16526..cff940a05a 100644 --- a/options/locale/locale_fi-FI.ini +++ b/options/locale/locale_fi-FI.ini @@ -1293,9 +1293,9 @@ issues.close_comment_issue=Kommentoi ja sulje issues.reopen_issue=Avaa uudelleen issues.reopen_comment_issue=Kommentoi ja avaa uudelleen issues.create_comment=Kommentoi -issues.closed_at=`sulki tämän ongelman %s` -issues.reopened_at=`uudelleenavasi tämän ongelman %s` -issues.commit_ref_at=`viittasi tähän ongelmaan kommitissa %s` +issues.closed_at=`sulki tämän ongelman %[2]s` +issues.reopened_at=`uudelleenavasi tämän ongelman %[2]s` +issues.commit_ref_at=`viittasi tähän ongelmaan kommitissa %[2]s` issues.author=Tekijä issues.role.owner=Omistaja issues.role.member=Jäsen @@ -2185,7 +2185,7 @@ settings.confirmation_string = Vahvistusteksti settings.delete_notices_2 = - Tämä toiminto poistaa pysyvästi tietovaraston %s mukaan lukien koodin, ongelmat, kommentit, wikidatan ja avustaja-asetukset. issues.filter_assginee_no_select = Kaikki käsittelijät issues.new.assign_to_me = Osoita itselle -pulls.closed_at = `sulki tämän vetopyynnön %s` +pulls.closed_at = `sulki tämän vetopyynnön %[2]s` tree_path_not_found_branch = Polkua %[1]s ei ole olemassa haarassa %[2]s transfer.no_permission_to_reject = Sinulla ei ole oikeutta hylätä tätä siirtoa. generate_repo = Luo tietovarasto @@ -2199,8 +2199,8 @@ issues.new.no_reviewers = Ei katselmoijia 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 kommitista %s` +issues.ref_pull_from = `viittasi tähän vetopyyntöön %[4]s %[2]s` +pulls.commit_ref_at = `viittasi tähän vetopyyntöön kommitista %[2]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 @@ -2255,14 +2255,14 @@ pulls.cmd_instruction_merge_warning = Varoitus: Asetusta ”Tunnista manu pulls.cmd_instruction_merge_desc = Yhdistä muutokset ja päivitä Forgejossa. pulls.cannot_auto_merge_desc = Tätä vetopyyntöä ei voida yhdistää automaattisesti ristiriitojen vuoksi. adopt_preexisting_success = Omaksuttu tiedostot ja luotu tietovarasto lähteestä %s -issues.comment_manually_pull_merged_at = manuaalisesti yhdisti kommitin %[1]s %[2]s tietovarastoon %[3]s +issues.comment_manually_pull_merged_at = manuaalisesti yhdistetty kommitti %[1]s %[2]s tietovarastoon %[3]s pulls.cmd_instruction_merge_title = Yhdistä pulls.has_merged = Epäonnistui: vetopyyntö on yhdistetty, joten et voi yhdistää uudelleen tai muuttaa kohdehaaraa. pulls.cmd_instruction_checkout_title = Uloskuittaus pulls.cmd_instruction_checkout_desc = Kuittaa ulos uusi haara projektitietovarastostasi ja testaa muutokset. pulls.clear_merge_message_hint = Yhdistämisviestin tyhjentäminen poistaa vain kommittiviestin sisällön ja säilyttää luodut git-trailerit, kuten "Co-Authored-By…". settings.protect_check_status_contexts_desc = Vaadi tilatarkistusten läpäisy ennen yhdistämistä. Kun käytössä, kommitit on ensin työnnettävä toiseen haaraan ja sitten yhdistettävä tai työnnettävä suoraan tätä sääntöä vastaavaan haaraan tilantarkistuksen jälkeen. Jos konteksteja ei löydy, viimeisen kommitin on oltava onnistunut kontekstista riippumatta. -issues.comment_pull_merged_at = yhdisti kommitin %[1]s %[2]s haaraan %[3]s +issues.comment_pull_merged_at = yhdistetty kommitti %[1]s %[2]s tietovarastoon %[3]s settings.pulls.enable_autodetect_manual_merge = Ota Tunnista manuaalinen yhdistäminen automaattisesti -asetus käyttöön (Huomaa: joissakin erityistapauksissa voi esiintyä virhearviointeja) pulls.no_merge_desc = Tätä vetopyyntöä ei voida yhdistää, koska kaikki tietovaraston yhdistämisvaihtoehdot ovat poistettu käytöstä. pulls.no_merge_not_ready = Tämä vetopyyntö ei ole valmis yhdistettäväksi. Tarkista katselmoinnin tila ja tilantarkistukset. @@ -2381,7 +2381,7 @@ wiki.page_name_desc = Kirjoita tämän wikisivun nimi. Joitain erikoisnimiä ova pulls.blocked_by_changed_protected_files_1 = Tämä vetopyyntö sisältää suojatun tiedoston ja on siksi estetty: pulls.status_checks_warning = Jotkin tarkistukset raportoivat varoituksia pulls.status_checks_error = Jotkin tarkistukset raportoivat virheitä -pulls.reopened_at = `avasi uudelleen tämän vetopyynnön %s` +pulls.reopened_at = `avasi uudelleen tämän vetopyynnön %[2]s` pulls.auto_merge_when_succeed = Yhdistä automaatisesti kun kaikki tarkistukset onnistuvat signing.wont_sign.error = Tapahtui virhe tarkistaessa voiko kommitin allekirjoittaa. signing.wont_sign.twofa = Sinulla tulee olla kaksivaiheinen todennus käytössä, jotta kommitit voi allekirjoittaa. diff --git a/options/locale/locale_fil.ini b/options/locale/locale_fil.ini index 8c9badb04b..7d1405f633 100644 --- a/options/locale/locale_fil.ini +++ b/options/locale/locale_fil.ini @@ -365,7 +365,7 @@ table_modal.label.columns = Mga Column link_modal.header = Magdagdag ng link link_modal.url = Url link_modal.description = Deskripsyon -link_modal.paste_reminder = Pahiwatig: Kapag may URL sa clipboard, maaari mong direktang i-paste sa editor para gumawa ng link. +link_modal.paste_reminder = Pahiwatig: Kapag may URL sa clipboard, maari mong direktang i-paste sa editor para gumawa ng link. [filter] string.asc = A - Z @@ -432,7 +432,7 @@ openid_connect_desc = Ang piniling OpenID URI ay hindi alam. Iugnay iyan sa bago invalid_code = Ang iyong confirmation code ay hindi wasto o nag-expire na. oauth_signin_title = Mag-sign in para pahintulutan ang naka-link na account invalid_code_forgot_password = Ang iyong confirmation code ay hindi wasto o nag-expire na. Mag-click dito para magsimula ng bagong session. -confirmation_mail_sent_prompt = Ang isang bagong email na pang-kumpirma ay ipinadala sa %s. Para kumpletuhin ang proseso ng pagrehistro, pakisuri ang iyong inbox at sundan ang ibinigay na link sa loob ng %s. Kung mali ang email, maaari kang mag-log in, at humingi ng isa pang email pang-kumpirma na ipapadala sa ibang address. +confirmation_mail_sent_prompt = Ang isang bagong email na pang-kumpirma ay ipinadala sa %s. Para kumpletuhin ang proseso ng pagrehistro, pakisuri ang iyong inbox at sundan ang ibinigay na link sa loob ng %s. Kung mali ang email, maari kang mag-log in, at humingi ng isa pang email pang-kumpirma na ipapadala sa ibang address. invalid_password = Ang iyong password ay hindi tugma sa password na ginamit para gawin ang account. twofa_scratch_used = Ginamit mo na ang scratch code. Na-redirect ka sa two-factor settings page para tanggalin ang device enrollment o mag-generate ng bagong scratch code. manual_activation_only = Makipag-ugnayan sa tagapangangasiwa ng site para kumpletuhin ang pagrehistro. @@ -484,7 +484,7 @@ admin.new_user.text = Mangyaring mag-click dito para ipamahala register_notify = Maligayang Pagdating sa %s register_notify.title = %[1]s, maligayang pagdating sa %[2]s register_notify.text_1 = ito ang iyong registration confirmation email para sa %s! -register_notify.text_2 = Maaari kang mag-sign in sa iyong account gamit ng iyong username: %s +register_notify.text_2 = Maari kang mag-sign in sa iyong account gamit ng iyong username: %s reset_password = I-recover ang iyong account reset_password.title = %s, nagkaroon kami ng hiling para i-recover ang iyong account reset_password.text = Kung ikaw ito, paki-click ang sumusunod na link para i-recover ang iyong account sa loob ng %s: @@ -535,7 +535,7 @@ totp_disabled.text_1 = Ngayon lang na-disable ang Time-based one-time password ( totp_disabled.no_2fa = Wala nang mga ibang paraan ng 2FA ang naka-configure, nangangahulugan na hindi na kailangang mag-log in sa iyong account gamit ang 2FA. removed_security_key.subject = May tinanggal na security key removed_security_key.text_1 = Tinanggal ngayon lang ang security key na "%[1]s" sa iyong account. -account_security_caution.text_1 = Kung ikaw ito, maaari mong ligtas na huwag pansinin ang mail na ito. +account_security_caution.text_1 = Kung ikaw ito, maari mong ligtas na huwag pansinin ang mail na ito. account_security_caution.text_2 = Kung hindi ito ikaw, nakompromiso ang iyong account. Mangyaring makipag-ugnayan sa mga tagapangasiwa ng site na ito. totp_enrolled.subject = Nag-activate ka ng TOTP bilang paraan ng 2FA totp_enrolled.text_1.has_webauthn = Na-enable mo lang ang TOTP para sa iyong account. Nangangahulugan ito na para sa lahat ng mga hinaharap na pag-login sa iyong account, kailangan mong gumamit ng TOTP bilang paraan ng 2FA o gamitin ang iyong mga security key. @@ -644,7 +644,7 @@ AccessToken = Token ng pag-access Biography = Byograpya Location = Lokasyon visit_rate_limit = Natugunan ang limitasyon sa rate ng malayuang pagbisita. -username_claiming_cooldown = Hindi ma-claim ang username na ito, dahil hindi pa tapos ang panahon ng cooldown. Maaari itong i-claim sa %[1]s. +username_claiming_cooldown = Hindi ma-claim ang username na ito, dahil hindi pa tapos ang panahon ng cooldown. Maari itong i-claim sa %[1]s. email_domain_is_not_allowed = Sumasalungat ang domain ng email address ng user %s sa EMAIL_DOMAIN_ALLOWLIST o EMAIL_DOMAIN_BLOCKLIST. Siguraduhing natakda mo ang email address nang tama. [user] @@ -685,7 +685,7 @@ followers.title.few = Mga tagasunod following.title.one = Sinusundan followers.title.one = Tagasunod public_activity.visibility_hint.self_public = Nakikita ng lahat ang iyong aktibidad, maliban sa mga interaksyon sa pribadong espasyo. I-configure. -public_activity.visibility_hint.admin_public = Nakikita ng lahat ang aktibidad na ito, ngunit bilang tagapangasiwa maaari mo ring makita ang mga interaksyon sa mga pribadong espasyo. +public_activity.visibility_hint.admin_public = Nakikita ng lahat ang aktibidad na ito, ngunit bilang tagapangasiwa maari mo ring makita ang mga interaksyon sa mga pribadong espasyo. public_activity.visibility_hint.self_private = Nakikita mo lang at mga tagapangasiwa ng instansya ang iyong aktibidad. I-configure. public_activity.visibility_hint.admin_private = Nakikita mo ang aktibidad na ito dahil isa kang tagapangasiwa, ngunit gusto ng user na panatilihin itong pribado. public_activity.visibility_hint.self_private_profile = Ikaw lang at ang mga tagapangasiwa ng instansya ang makakakita ng iyong aktibidad dahil pribado ang iyong profile. I-configure. @@ -842,7 +842,7 @@ gpg_key_verify = I-verify gpg_invalid_token_signature = Ang ibinigay na GPG key, signature, at token ay hindi tumutugma o luma. gpg_token_required = Kailangan mong magbigay ng signature para sa token sa ibaba gpg_token = Token -gpg_token_help = Maaari kang mag-generate ng signature gamit ng: +gpg_token_help = Maari kang mag-generate ng signature gamit ng: gpg_token_signature = Naka-armor na GPG signature key_signature_gpg_placeholder = Nagsisimula sa "-----BEGIN PGP SIGNATURE-----" verify_gpg_key_success = Na-verify na ang GPG key na "%s". @@ -851,7 +851,7 @@ ssh_key_verify = I-verify ssh_invalid_token_signature = Ang ibinigay na SSH key, signature, o token ay hindi tumutugma o luma. ssh_token_required = Kailangan mong magbigay ng signature para sa token sa ibaba ssh_token = Token -ssh_token_help = Maaari kang mag-generate ng signature gamit ng: +ssh_token_help = Maari kang mag-generate ng signature gamit ng: ssh_token_signature = Naka-armor na SSH signature key_signature_ssh_placeholder = Nagsisimula sa "-----BEGIN SSH SIGNATURE-----" verify_ssh_key_success = Na-verify na ang SSH key na "%s". @@ -912,10 +912,10 @@ create_oauth2_application_success = Matagumpay kang gumawa ang bagong OAuth2 app oauth2_confidential_client = Kumpidensyal na kliyente. Piliin para sa mga app na pinapatilihing kumpidensyal ang sikreto, tulad ng mga web app. Huwag piliin para sa mga web app kasama ang mga desktop at mobile app. twofa_desc = Para protektahin ang iyong account laban sa pagnanakaw ng password, pwede mo gamitin ang iyong smartphone o ibang device para sa pagtanggap ng time-based one-time password ("TOTP"). twofa_scratch_token_regenerated = Ang iyong isang-beses na paggamit na recovery key ngayon ay %s. Ilagay ito sa ligtas na lugar, dahil hindi na ito ipapakita muli. -regenerate_scratch_token_desc = Kapag nawala mo ang iyong recovery key o ginamit mo na oara mag-sign in, maaari mong i-reset dito. +regenerate_scratch_token_desc = Kapag nawala mo ang iyong recovery key o ginamit mo na oara mag-sign in, maari mong i-reset dito. twofa_disable_desc = Ang pag-disable ng authentikasyong two-factor ay gagawing hindi gaanong ligtas ang iyong account. Magpatuloy? twofa_enrolled = Matagumpay na na-enroll ang iyong account. Ilagay ang iyong isang-beses na paggamit na recovery key (%s) sa isang ligtas na lugar, dahil hindi na ito ipapakita muli. -webauthn_desc = Ang mga security key ay isang hardware device na naglalaman ng mga cryptographic key. Maaari silang gamitin para sa authentikasyong two-factor. Ang mga security key ay dapat suportahan ang WebAuthn Authenticator na standard. +webauthn_desc = Ang mga security key ay isang hardware device na naglalaman ng mga cryptographic key. Maari silang gamitin para sa authentikasyong two-factor. Ang mga security key ay dapat suportahan ang WebAuthn Authenticator na standard. remove_oauth2_application = Tanggalin ang OAuth2 Application remove_oauth2_application_desc = Ang pagtanggal ng OAuth2 application ay babawiin ang access sa lahat ng mga naka-sign na access token. Magpatuloy? remove_oauth2_application_success = Binura na ang application. @@ -931,13 +931,13 @@ oauth2_regenerate_secret = I-regenerate ang sikreto oauth2_regenerate_secret_hint = Nawala mo ang iyong sikreto? oauth2_client_secret_hint = Ang sikreto ay hindi ipapakita muli pagkatapos umalis ka o i-refresh ang page na ito. Mangyaring siguraduhin na na-save mo iyan. oauth2_application_edit = I-edit -twofa_recovery_tip = Kapag mawala mo ang iyong device, maaari kang gumamit ng isang isang-beses na paggamit na recovery key para makakuha muli ng access sa iyong account. +twofa_recovery_tip = Kapag mawala mo ang iyong device, maari kang gumamit ng isang isang-beses na paggamit na recovery key para makakuha muli ng access sa iyong account. twofa_is_enrolled = Ang iyong account ay kasalukuyang naka-enroll sa autentikasyong two-factor. twofa_not_enrolled = Kasalukuyang hindi naka-enroll ang iyong account sa authentikasyong two-factor. twofa_disable = I-disable ang authentikasyong two-factor twofa_scratch_token_regenerate = I-regenerate ang isang-beses na paggamit na recovery key twofa_enroll = Mag-enroll sa authentikasyong two-factor -twofa_disable_note = Maaari mong i-disable ang authentikasyong two-factor kapag kinakailangan. +twofa_disable_note = Maari mong i-disable ang authentikasyong two-factor kapag kinakailangan. twofa_disabled = Na-disable na ang authentikasyong two-factor. scan_this_image = I-scan ang image na ito gamit ng iyong aplikasyong pang-authentikasyon: or_enter_secret = O ilagay ang sikreto: %s @@ -1005,8 +1005,8 @@ language.description = Mase-save ang wika sa iyong account at gagamitin bilang d language.localization_project = Tulungan kaming isalin ang Forgejo sa iyong wika! Matuto pa. pronouns_custom_label = Mga pasadyang pronoun 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 cooldown ng %[1]d araw, maari 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, maari mo pa ring ma-claim muli ang lumang username sa panahon ng panahon ng cooldown. 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 @@ -1071,7 +1071,7 @@ readme_helper_desc = Ito ang lugar kung saan makakasulat ka ng kumpletong deskri trust_model_helper_collaborator_committer = Katulong+Committer: I-trust ang mga signature batay sa mga katulong na tumutugma sa committer mirror_interval = Interval ng mirror (ang mga wastong unit ng oras ay "h", "m", "s"). 0 para i-disable ang periodic sync. (Pinakamababang interval: %s) transfer.reject_desc = Kanselahin ang pag-transfer mula sa "%s" -mirror_lfs_endpoint_desc = Ang sync ay susubukang gamitin ang clone url upang matukoy ang LFS server. Maaari ka rin tumukoy ng isang custom na endpoint kapag ang LFS data ng repositoryo ay nilalagay sa ibang lugar. +mirror_lfs_endpoint_desc = Ang sync ay susubukang gamitin ang clone url upang matukoy ang LFS server. Maari ka rin tumukoy ng isang custom na endpoint kapag ang LFS data ng repositoryo ay nilalagay sa ibang lugar. adopt_search = Ilagay ang username para maghanap ng mga unadopted na repositoryo… (iwanang walang laman para hanapin lahat) object_format = Format ng object readme_helper = Pumili ng README file template @@ -1164,8 +1164,8 @@ tree_path_not_found_commit = Hindi umiiral ang path na %[1]s sa commit %[2]s tree_path_not_found_branch = Hindi umiiral ang daanang %[1]s sa branch %[2]s migrate_items_pullrequests = Mga hiling sa paghila archive.pull.nocomment = Naka-archive ang repositoryong ito. Hindi ka makakakomento sa mga pull request. -archive.title = Naka-archive ang repositoryong ito. Maaari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado ito, tulad ng pagtulak at paggawa ng mga isyu, pull request o mga komento. -archive.title_date = Naka-archive ang repositoryo na ito noong %s. Maaari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado nito, tulad ng pagtulak o paggawa ng mga bagong isyu, mga pull request, o komento. +archive.title = Naka-archive ang repositoryong ito. Maari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado ito, tulad ng pagtulak at paggawa ng mga isyu, pull request o mga komento. +archive.title_date = Naka-archive ang repositoryo na ito noong %s. Maari mong itignan ang mga file at i-clone ito, pero hindi ka makakagawa ng anumang pagbabago sa estado nito, tulad ng pagtulak o paggawa ng mga bagong isyu, mga pull request, o komento. pulls = Mga hiling sa paghila activity.merged_prs_count_n = Mga naisamang hiling sa paghila wiki.last_updated = Huling binago %s @@ -1183,7 +1183,7 @@ issues.action_open = Buksan issues.closed_title = Sarado issues.reopen_issue = Buksang muli pulls.merged = Naisama na -pulls.merged_info_text = Maaari nang burahin ang branch %s. +pulls.merged_info_text = Maari nang burahin ang branch %s. milestones.update_ago = Binago %s activity.closed_issue_label = Sarado activity.merged_prs_label = Naisama @@ -1205,7 +1205,7 @@ migrate.clone_address_desc = Ang HTTP(S) o Git "clone" URL ng umiiral na reposit need_auth = Awtorisasyon migrate.github_token_desc = Maaari kang maglagay ng isa o higit pang mga token na hinihiwalay ng kuwit dito upang gawing mas-mabilis ang pagmigrate dahil sa rate limit ng GitHub API. BABALA: Ang pagabuso ng feature na ito ay maaaring maglabag sa patakaran ng tagapagbigay ng serbisyo at maaaring magdulot ng pag-block ng account. template.invalid = Kailangang pumili ng kahit isang template na repositoryo -migrate_options_lfs_endpoint.description = Susubukan ng migration na gamitin ang iyong Git remote upang matukoy ang LFS server. Maaari mong magtiyak ng custom na endpoint kapag ang LFS data ng repositoryo ay nakalagay sa ibang lugar. +migrate_options_lfs_endpoint.description = Susubukan ng migration na gamitin ang iyong Git remote upang matukoy ang LFS server. Maari mong magtiyak ng custom na endpoint kapag ang LFS data ng repositoryo ay nakalagay sa ibang lugar. blame.ignore_revs.failed = Nabigong hindi pansinin ang mga rebisyon sa .git-blame-ignore-revs. tree_path_not_found_tag = Hindi umiiral ang path na %[1]s sa tag %[2]s form.reach_limit_of_creation_n = Naabot na ng may-ari ang limitasyon na %d mga repositoryo. @@ -1471,10 +1471,10 @@ activity.new_issue_label = Nabuksan activity.merged_prs_count_1 = Naisamang hiling sa paghila activity.opened_prs_count_1 = Inimungkahing hiling sa paghila activity.opened_prs_label = Inimungkahi -pulls.reopened_at = `binuksan muli ang hiling sa paghila %s` +pulls.reopened_at = `nabuksang muli ang hiling sa paghatak na %[2]s` issues.opened_by_fake = binuksan ang %[1]s ni/ng %[2]s pulls.reopen_failed.base_branch = Hindi mabuksang muli ang hiling sa paghatak na ito dahil hindi na umiiral ang base branch. -issues.reopened_at = `binuksang muli ang isyung ito %s` +issues.reopened_at = `binuksang muli ang isyung ito %[2]s` pulls.reopen_failed.head_branch = Hindi mabubuksan muli ang hiling sa paghila, dahil hindi na umiiral ang head branch. settings.event_pull_request_desc = Binuksan, sinara, muling binuksan, o binago ang hiling sa paghatak. activity.opened_prs_count_n = Mga inimungkahing hiling sa paghila @@ -1500,7 +1500,7 @@ issues.content_history.created = ginawa editor.patching = Pina-patch: editor.fail_to_apply_patch = Hindi malapat ang patch na "%s" settings.danger_zone = Mapanganib na lugar -issues.closed_at = `isinara ang isyung ito %s` +issues.closed_at = `isinara ang isyung ito %[2]s` settings.collaboration.admin = Tagapangasiwa settings.admin_settings = Mga setting ng tagapangasiwa issues.start_tracking_history = `sinimulan ang trabaho %s` @@ -1627,7 +1627,7 @@ projects.column.edit_title = Pangalan projects.column.new_title = Pangalan projects.card_type.desc = Mga preview ng card commits.desc = I-browse ang history ng pagbabago ng source code. -commits.search.tooltip = Maaari kang mag-prefix ng mga keyword gamit ang "author:", "committer:", "after:", o "before:", hal. "revert author:Nijika before:2022-10-09". +commits.search.tooltip = Maari kang mag-prefix ng mga keyword gamit ang "author:", "committer:", "after:", o "before:", hal. "revert author:Nijika before:2022-10-09". issues.force_push_codes = `puwersahang itinulak ang %[1]s mula %[2]s sa %[4]s %[6]s` issues.push_commit_1 = idinagdag ang %d commit %s issues.push_commits_n = idinagdag ang %d mga commit %s @@ -1707,7 +1707,7 @@ issues.action_milestone = Milestone issues.action_milestone_no_select = Walang milestone issues.delete_branch_at = `binura ang branch na %s %s` issues.filter_label = Label -issues.filter_label_exclude = `Gamitin ang Alt + Click para hindi isama ang mga label` +issues.filter_label_exclude = `Gamitin ang alt + click/enter para hindi isama ang mga label` issues.filter_label_no_select = Lahat ng mga label issues.filter_milestone_closed = Mga nakasarang milestone issues.filter_assignee = Mangangasiwa @@ -1771,7 +1771,7 @@ issues.lock = I-lock ang usapan issues.unlock = I-unlock ang usapan issues.unlock_comment = na-unlock ang usapang ito %s issues.unlock.notice_1 = - Makakakomento muli ang lahat ng mga tao sa isyung ito. -issues.unlock.notice_2 = - Maaari mong i-lock muli ang isyung ito sa hinaharap. +issues.unlock.notice_2 = - Maari mong i-lock muli ang isyung ito sa hinaharap. issues.comment_on_locked = Hindi ka makakakomento sa naka-lock na isyu. issues.closed_by_fake = ni/ng %[2]s ay isinara %[1]s issues.comment_manually_pull_merged_at = manwal na isinama ang commit %[1]s sa %[2]s %[3]s @@ -1787,10 +1787,10 @@ issues.label_archive_tooltip = Ang mga naka-archive na label ay hindi isasama bi issues.is_stale = May mga pagbabago sa PR na ito mula sa pagsuri na ito issues.role.first_time_contributor = Unang-beses na contributor issues.lock.notice_1 = - Hindi makakadagdag ng mga bagong komento ang mga ibang user sa isyu na ito. -issues.lock.notice_3 = - Maaari mong i-unlock muli ang isyung ito sa hinaharap. +issues.lock.notice_3 = - Maari mong i-unlock muli ang isyung ito sa hinaharap. issues.label_deletion_desc = Ang pagbura ng label ay tatanggalin ito sa lahat ng mga isyu. Magpatuloy? -issues.commit_ref_at = `isinangguni ang isyu na ito mula sa commit %s` -issues.ref_issue_from = `isinangguni ang isyu na ito sa %[3]s %[1]s` +issues.commit_ref_at = `isinangguni ang isyu na ito mula sa commit %[2]s` +issues.ref_issue_from = `isinangguni ang isyu na ito sa %[4]s %[2]s` issues.num_participants_one = %d kasali issues.attachment.download = `I-click para i-download ang "%s" ` issues.num_participants_few = %d mga kasali @@ -1815,10 +1815,10 @@ issues.sign_in_require_desc = Mag-sign in upang sumali sa usapa issues.num_comments = %d mga komento issues.role.contributor_helper = Nakaraang nag-commit ang user na ito sa repositoryo na ito. issues.comment_pull_merged_at = isinama ang commit %[1]s sa %[2]s %[3]s -pulls.commit_ref_at = `isinangguni ang hiling sa paghila mula sa isang commit %s` +pulls.commit_ref_at = `isinangguni ang hiling sa paghila mula sa isang commit %[2]s` wiki.last_commit_info = Binago ni %s ang pahinang ito %s issues.content_history.edited = binago -issues.ref_pull_from = `isinangguni ang hiling sa paghila na ito %[3]s %[1]s` +issues.ref_pull_from = `isinangguni ang hiling sa paghila na ito %[4]s %[2]s` pulls.merged_title_desc_few = isinali ang %[1]d mga commit mula sa %[2]s patungong %[3]s %[4]s settings.org_not_allowed_to_be_collaborator = Hindi maaaring idagdag ang mga organisasyon bilang tagatulong. settings.add_collaborator_success = Naidagdag ang tagatulong. @@ -1828,7 +1828,7 @@ pulls.create = Gumawa ng hiling sa paghila issues.dependency.pr_close_blocked = Kailangan mong isara ang lahat ng mga isyu na humaharang sa hiling sa paghila na ito bago mo ito isama. pulls.delete.title = Burahin ang hiling sa paghila na ito? issues.dependency.pr_closing_blockedby = Hinarang ng mga sumusunod na isyu mula sa pagsara ng hiling sa paghila na ito -pulls.closed_at = `isinara ang hiling sa paghila na ito %s` +pulls.closed_at = `isinara ang hiling sa paghila na %[2]s` pulls.close = Isara ang hiling sa paghila pulls.cmd_instruction_hint = Tingnan ang mga panuto para sa command line project = Mga proyekto @@ -1836,8 +1836,8 @@ issues.content_history.deleted = binura pulls.no_results = Walang mga nahanap na resulta. pulls.closed = Sarado ang hiling sa paghila pulls.is_closed = Naisara na ang hiling sa paghila. -issues.ref_closing_from = `nagsangguni ang isyu mula sa hiling sa paghila %[3]s na magsasara sa isyu, %[1]s` -issues.ref_reopening_from = `nagsangguni ang isyu na ito mula sa hiling sa paghila %[3]s na muling bubukas nito, %[1]s` +issues.ref_closing_from = `nagsangguni ang isyu mula sa hiling sa paghila %[4]s na magsasara sa isyu, %[2]s` +issues.ref_reopening_from = `nagsangguni ang isyu na ito mula sa hiling sa paghila %[4]s na muling bubukas, %[2]s` issues.ref_closed_from = `isinara ang isyung ito %[4]s%[2]s` issues.review.wait = hiniling sa pagsuri %s issues.review.reject = hinihiling ang mga pagbago %s @@ -2015,14 +2015,14 @@ wiki.cancel = Kanselahin settings.collaboration.undefined = Hindi Natukoy settings.federation_settings = Mga Setting ng Federation settings = Mga Setting -settings.desc = Ang mga setting ang lugar kung saan maaari mong ipamahala ang mga setting para sa repositoryo +settings.desc = Ang mga setting ang lugar kung saan maari mong ipamahala ang mga setting para sa repositoryo pulls.collapse_files = I-collapse ang lahat ng mga file pulls.add_prefix = Magdagdag ng %s na prefix pulls.still_in_progress = Ginagawa pa? activity.title.prs_1 = %d hiling sa paghila activity.active_issues_count_n = %d mga aktibong isyu pulls.required_status_check_missing = Nawawala ang ilang mga kinakailangang pagsusuri. -pulls.required_status_check_administrator = Bilang tagapangasiwa, maaari mo pa ring isama ang hiling sa paghila na ito. +pulls.required_status_check_administrator = Bilang tagapangasiwa, maari mo pa ring isama ang hiling sa paghila na ito. pulls.blocked_by_approvals = Wala pang sapat na pag-apruba ang hiling sa paghila na ito. %d ng %d na pag-apruba ang ibinigay. settings.options = Repositoryo wiki.back_to_wiki = Bumalik sa pahina ng wiki @@ -2110,7 +2110,7 @@ settings.actions_desc = I-enable ang mga kasamang CI/CD pipeline gamit ang Forge settings.admin_indexer_commit_sha = Huling na-index na commit settings.admin_indexer_unindexed = Hindi naka-index settings.transfer_notices_3 = - Kung pribado ang repositoryo at ilipat sa isang indibidwal na user, ang aksyon na ito ay sinisigurado na ang user ay may pahintulot na basahin (at palitan ang mga pahintulot kung kailangan). -settings.convert_desc = Maaari mong i-convert ang repositoryo na ito sa regular na repositoryo. Hindi ito mababawi. +settings.convert_desc = Maari mong i-convert ang repositoryo na ito sa regular na repositoryo. Hindi ito mababawi. settings.transfer.button = Ilipat ang pagmamay-ari settings.signing_settings = Mga setting sa pagpapatunay ng pag-sign settings.admin_enable_close_issues_via_commit_in_any_branch = Isara ang isyu sa pamamagitan ng commit na ginawa sa hindi default na branch @@ -2137,7 +2137,7 @@ settings.deploy_key_deletion = Tanggalin ang deploy key settings.protect_enable_push = I-enable ang pagtulak settings.discord_icon_url.exceeds_max_length = Kailangang bababa o equal sa 2048 characters ang URL ng icon settings.protected_branch.save_rule = I-save ang rule -settings.mirror_settings.docs.can_still_use = Bagama't na hindi ka makakabago ng mga umiiral na mirror o gumawa ng bago, maaari mo pa rin gamitin ang iyong umiiral na mirror. +settings.mirror_settings.docs.can_still_use = Bagama't na hindi ka makakabago ng mga umiiral na mirror o gumawa ng bago, maari mo pa rin gamitin ang iyong umiiral na mirror. settings.slack_color = Kulay settings.discord_icon_url = URL ng icon settings.convert_fork_confirm = I-convert ang repositoryo @@ -2254,7 +2254,7 @@ settings.pulls.allow_rebase_update = I-enable ang pag-update ng hiling sa paghil settings.admin_enable_health_check = I-enable ang pagsusuri ng kalusugan ng repositoryo (git fsck) settings.new_owner_has_same_repo = Ang bagong may-ari ay may repositoryo na may katulad na pangalan. Mangyaring pumili ng ibang pangalan. settings.convert = I-convert sa regular na repositoryo -settings.convert_fork_desc = Maaari mong i-convert ang fork na ito bilang regular na repositoryo. Hindi ito mababawi. +settings.convert_fork_desc = Maari mong i-convert ang fork na ito bilang regular na repositoryo. Hindi ito mababawi. settings.convert_fork_notices_1 = Ang operasyon na ito ay ico-convert ang fork bilang regular na repositoryo at hindi mababawi. settings.transfer_abort_invalid = Hindi mo makakansela ang isang hindi umiiral na paglipat ng repositoryo. settings.transfer_quota_exceeded = Ang bagong may-ari (%s) ay lumalagpas sa quota. Hindi nailipat ang repositoryo. @@ -2290,8 +2290,8 @@ settings.webhook.headers = Mga header settings.webhook.payload = Nilalaman settings.webhook.body = Katawan settings.webhook.replay.description = I-replay ang webhook na ito. -settings.webhook.delivery.success = May nadagdag na event sa delivery queue. Maaari magtagal ng ilang segundo bago makita sa delivery history. -settings.githooks_desc = Pinapagana ng Git ang mga Git hook. Maaari mong baguhin ang mga hook file sa ibaba para mag-set up ng mga custom na operasyon. +settings.webhook.delivery.success = May nadagdag na event sa delivery queue. Maari magtagal ng ilang segundo bago makita sa delivery history. +settings.githooks_desc = Pinapagana ng Git ang mga Git hook. Maari mong baguhin ang mga hook file sa ibaba para mag-set up ng mga custom na operasyon. settings.githook_name = Pangalan ng hook settings.githook_content = Nilalaman ng hook settings.update_githook = I-update ang hook @@ -2362,7 +2362,7 @@ settings.mirror_settings.docs.pull_mirror_instructions = Para mag-set up ng pull milestones.invalid_due_date_format = Kailangang "yyyy-mm-dd" na format ang takdang petsa. signing.wont_sign.nokey = Walang key ang instansya na ito para i-sign ang commit na ito. activity.title.releases_1 = %d paglabas -settings.mirror_settings.docs.more_information_if_disabled = Maaari kang matuto pa tungkol sa mga push at pull na mirror dito: +settings.mirror_settings.docs.more_information_if_disabled = Maari kang matuto pa tungkol sa mga push at pull na mirror dito: settings.branches.switch_default_branch = Magpalit ng default branch settings.convert_notices_1 = Ang operasyon na ito ay ico-covert ang mirror sa regular na repositoryo at hindi mababawi. settings.convert_fork_succeed = Na-convert na ang fork sa regular na repositoryo. @@ -2732,7 +2732,7 @@ settings.protect_protected_file_patterns = Mga pattern ng nakaprotektang file (h settings.update_protect_branch_success = Binago na ang branch protection rule na "%s". settings.remove_protected_branch_success = Tinanggal ang branch protection rule na "%s". settings.tags.protection.pattern = Pattern ng tag -settings.tags.protection.pattern.description = Maaari kang gumamit ng iisang pangalan o glob pattern o regular expression para magtugma ng maraming tag. Magbasa pa sa guide ng mga nakaprotektang tag. +settings.tags.protection.pattern.description = Maari kang gumamit ng iisang pangalan o glob pattern o regular expression para magtugma ng maraming tag. Magbasa pa sa guide ng mga nakaprotektang tag. settings.thread_id = ID ng thread settings.matrix.room_id = ID ng room diff.has_escaped = May mga nakatagong Unicode character ang linya na ito @@ -2746,7 +2746,7 @@ diff.bin = BIN settings.default_update_style_desc = Ang default na istilio na gagamitin sa pag-update ng mga hiling sa paghila na nalilipas sa base branch. pulls.sign_in_require = Mag-sign in para gumawa ng bagong hiling sa paghila. new_from_template = Gumamit ng template -new_from_template_description = Maaari kang pumili ng umiiral na repository template sa instansya na ito at i-apply ang mga setting nito. +new_from_template_description = Maari kang pumili ng umiiral na repository template sa instansya na ito at i-apply ang mga setting nito. new_advanced = Mga advanced na setting new_advanced_expand = I-click para i-expand auto_init_description = Simulan ang kasaysayan ng Git gamit ang README at opsyonal na magdagdag ng mga lisensya at .gitignore na file. @@ -2780,7 +2780,6 @@ settings.event_action_recover = I-recover settings.event_action_success = Matagumpay settings.event_action_success_desc = Matagumpay na natapos ang Action Run. settings.event_action_recover_desc = Matagumpay na natapos ang Action Run pagkatapos na nabigo ang huling Action Run sa katulad na workflow. -issues.filter_type.all_pull_requests = Lahat ng mga hiling sa paghila [search] commit_kind = Maghanap ng mga commit… @@ -3206,7 +3205,7 @@ self_check.database_collation_mismatch = Inaasahan ang database na gamitin ang c auths.oauth2_admin_group = Group claim value para sa mga tagapangasiwa. (Opsyonal - kinakailangan ang claim name sa itaas) auths.tip.facebook = Magrehistro ng bagong application sa %s at idagdag ang produktong "Facebook Login" users.restricted.description = Payagan lamang ang interaksyon sa mga repositoryo at organisasyon kung saan ang user ay dinagdag bilang tagatulong. Iniiwasan nito ang pag-access sa publikong repositoryo sa instansya na ito. -users.local_import.description = Payagan ang pag-import ng mga repositoryo mula sa local file system ng user. Maaari itong maging isyu sa seguridad. +users.local_import.description = Payagan ang pag-import ng mga repositoryo mula sa local file system ng user. Maari itong maging isyu sa seguridad. emails.delete = Burahin ang Email emails.deletion_success = Binura na ang email address. auths.oauth2_required_claim_value = Kinakailangan na claim value @@ -3451,8 +3450,8 @@ teams.owners_permission_desc = Ang mga owner ay may punong access sa lah teams.add_nonexistent_repo = Hindi pa umiiral ang repositoryo na sinusubukan mong idagdag. Mangyaring gawin iyan muna. teams.all_repositories = Lahat ng mga repositoryo teams.all_repositories_helper = Ang koponan ay may access sa lahat ng mga repositoryo. Ang pagpili nito ay idadagdag ang lahat ng mga umiiral na repositoryo sa koponan. -settings.change_orgname_redirect_prompt.with_cooldown.few = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang pangalan sa panahon ng cooldown. -settings.change_orgname_redirect_prompt.with_cooldown.one = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw. Maaari mo pa ring ma-claim muli ang lumang pangalan ng panahon ng cooldown. +settings.change_orgname_redirect_prompt.with_cooldown.few = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang pangalan sa panahon ng cooldown. +settings.change_orgname_redirect_prompt.with_cooldown.one = Magiging available ang lumang pangalan ng organisasyon sa lahat pagkatapos ng panahon ng cooldown ng %[1]d araw, maari mo pa ring ma-claim muli ang lumang pangalan ng panahon ng cooldown. [packages] diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index e522d5ab92..3fcfda18bd 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -1062,8 +1062,8 @@ language.localization_project = Aidez-nous à traduire Forgejo dans votre langue language.description = Cette langue sera enregistrée dans votre compte et utilisée comme langue par défaut après votre connexion. user_block_yourself = Vous ne pouvez pas vous bloquer vous même. pronouns_custom_label = Pronoms personnalisés -change_username_redirect_prompt.with_cooldown.one = L'ancien pseudonyme sera disponible pour n'importe qui après une période d'%[1]d jour. Vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période. -change_username_redirect_prompt.with_cooldown.few = L'ancien pseudonyme sera disponible pour n'importe qui après une période de %[1]d jours. Vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période. +change_username_redirect_prompt.with_cooldown.one = L'ancien pseudonyme sera disponible pour n'importe qui après une période d'%[1]d jour, vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période. +change_username_redirect_prompt.with_cooldown.few = L'ancien pseudonyme sera disponible pour n'importe qui après une période de %[1]d jours, vous pouvez toujours réclamer votre ancien pseudonyme pendant cette période. quota.rule.exceeded = Dépassé regenerate_token = Régénérer access_token_regeneration = Régénérer le token d'accès @@ -1579,7 +1579,7 @@ issues.remove_ref_at=`a supprimé la référence %s %s.` issues.add_ref_at=`a ajouté la référence %s %s.` issues.delete_branch_at=`a supprimé la branche %s %s.` issues.filter_label=Label -issues.filter_label_exclude=`Utilisez Alt + Click pour exclure les étiquettes.` +issues.filter_label_exclude=`Utilisez Alt + Clic/entrée pour exclure les labels.` issues.filter_label_no_select=Toutes les labels issues.filter_label_select_no_label=Aucun label issues.filter_milestone=Jalon @@ -1653,13 +1653,13 @@ issues.close_comment_issue=Fermer avec le commentaire issues.reopen_issue=Rouvrir issues.reopen_comment_issue=Réouvrir avec le commentaire issues.create_comment=Commenter -issues.closed_at=`a fermé ce ticket %s` -issues.reopened_at=`a rouvert ce ticket %s` -issues.commit_ref_at=`a référencé ce ticket depuis une révision %s` -issues.ref_issue_from=`a fait référence à ce ticket %[3]s %[1]s` -issues.ref_pull_from=`a fait référence à cette demande d'ajout %[3]s %[1]s` -issues.ref_closing_from=`a fait référence à une demande d'ajout %[3]s qui clora ce ticket, %[1]s` -issues.ref_reopening_from=`a référencé ce ticket dans une pull request %[3]s qui va ré-ouvrir ce ticket, %[1]s` +issues.closed_at=`a fermé ce ticket %[2]s.` +issues.reopened_at=`a rouvert ce ticket %[2]s.` +issues.commit_ref_at=`a référencé ce ticket depuis une révision %[2]s.` +issues.ref_issue_from=`a fait référence à %[4]s ce ticket %[2]s.` +issues.ref_pull_from=`a fait référence à cette demande d'ajout %[4]s %[2]s.` +issues.ref_closing_from=`a fait référence à une demande d'ajout %[4]s qui clora ce ticket, %[2]s.` +issues.ref_reopening_from=`a référencé une pull request %[4]s qui va ré-ouvrir ce ticket %[2]s` issues.ref_closed_from=`a fermé ce ticket %[4]s %[2]s` issues.ref_reopened_from=`a rouvert ce ticket %[4]s %[2]s.` issues.ref_from=`de %[1]s` @@ -1967,8 +1967,8 @@ pulls.update_branch_success=La mise à jour de la branche a réussi pulls.update_not_allowed=Vous n'êtes pas autorisé à mettre à jour la branche pulls.outdated_with_base_branch=Cette branche est désynchronisée avec la branche de base pulls.close=Fermer la demande d’ajout -pulls.closed_at=`a fermé cette demande d'ajout %s` -pulls.reopened_at=`a rouvert cette demande d'ajout %s` +pulls.closed_at=`a fermé cette demande d'ajout %[2]s.` +pulls.reopened_at=`a rouvert cette demande d'ajout %[2]s.` pulls.cmd_instruction_hint=Voir les instructions en ligne de commande pulls.cmd_instruction_checkout_title=Basculer pulls.cmd_instruction_checkout_desc=Depuis votre dépôt, basculer sur une nouvelle branche et tester des modifications. @@ -2762,7 +2762,7 @@ issues.blocked_by_user = Vous ne pouvez pas créer de tickets sur ce dépôt car pulls.blocked_by_user = Vous ne pouvez pas créer une pull request sur ce dépôt car vous êtes bloqué par son propriétaire. wiki.cancel = Annuler settings.wiki_globally_editable = Permettre l'édition du wiki a tout le monde -pulls.commit_ref_at = `a référencé cette pull request depuis un commit %s` +pulls.commit_ref_at = `a référencé cette pull request depuis le commit %[2]s` settings.new_owner_blocked_doer = Le nouveau propriétaire vous a bloqué. settings.enter_repo_name = Confirmez en entrant le propriétaire et le nom du dépôt exactement comme affiché : settings.wiki_rename_branch_main = Normalise le nom de la branche du Wiki @@ -3058,8 +3058,8 @@ teams.invite.by=Invité par %s teams.invite.description=Veuillez cliquer sur le bouton ci-dessous pour rejoindre l’équipe. follow_blocked_user = Vous ne pouvez pas suivre cette organisation car elle vous a bloqué. open_dashboard = Ouvrir le tableau de bord -settings.change_orgname_redirect_prompt.with_cooldown.few = L'ancien nom d'organisation sera disponible pour n'importe qui après une période de %[1]d jours. Vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période. -settings.change_orgname_redirect_prompt.with_cooldown.one = L'ancien nom d'organisation sera disponible pour n'importe qui après une période d'%[1]d jour. Vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période. +settings.change_orgname_redirect_prompt.with_cooldown.few = L'ancien nom d'organisation sera disponible pour n'importe qui après une période de %[1]d jours, vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période. +settings.change_orgname_redirect_prompt.with_cooldown.one = L'ancien nom d'organisation sera disponible pour n'importe qui après une période d'%[1]d jour, vous pouvez toujours réclamer votre ancien nom d'organisation pendant cette période. [admin] dashboard=Tableau de bord @@ -4091,4 +4091,4 @@ issues.write = Écrire : Fermer des tickets et gérer les métadonnées t pulls.read = Lire : Lire et créer des demandes de tirage. [translation_meta] -test = Ceci est une chaîne de test. Elle n'est pas affichée dans Forgejo mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce difficile 100 % de complétion. :-) +test = Ceci est une chaîne de test. Elle n'est pas affichée dans l'interface de Forgejo mais est utilisée à des fins de test. N'hésitez pas à entrer 'ok' pour gagner du temps (ou un fait amusant de votre choix) pour atteindre ce difficile 100 % de complétion. :-) diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index 3bb06e8c21..d2d960b627 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -1219,11 +1219,11 @@ issues.close_comment_issue = Dún le trácht issues.reopen_issue = Athoscail issues.reopen_comment_issue = Athoscail le trácht issues.create_comment = Trácht -issues.closed_at = `dhún an cheist seo %s` -issues.reopened_at = `athoscail an t-eagrán seo %s` -issues.commit_ref_at = `rinne tagairt don cheist seo ó ghealltanas %s` -issues.ref_issue_from = `rinne dagairt don cheist seo %[3]s %[1]s` -issues.ref_pull_from = `rinne dagairt don iarratas tarraingthe seo %[3]s %[1]s` +issues.closed_at = `dhún an cheist seo %[2]s` +issues.reopened_at = `athoscail an t-eagrán seo %[2]s` +issues.commit_ref_at = `rinne tagairt don cheist seo ó ghealltanas %[2]s` +issues.ref_issue_from = `rinne dagairt don cheist seo %[4]s %[2]s` +issues.ref_pull_from = `rinne dagairt don iarratas tarraingthe seo %[4]s %[ 2]s` issues.ref_closed_from = `dhún an cheist seo %[4]s %[2]s` issues.ref_reopened_from = `d'athoscail an eagrán seo %[4]s %[2]s` issues.ref_from = `ó %[1]s` @@ -1456,8 +1456,8 @@ pulls.update_branch_success = Bhí nuashonrú brainse rathúil pulls.update_not_allowed = Ní cheadaítear duit brainse a nuashonrú pulls.outdated_with_base_branch = Tá an brainse seo as dáta leis an mbunbhrainse pulls.close = Dún Iarratas Tarraing -pulls.closed_at = `dhún an t-iarratas tarraingthe seo %s` -pulls.reopened_at = `athoscail an t-iarratas tarraingthe seo %s` +pulls.closed_at = `dhún an t-iarratas tarraingthe seo %[2]s` +pulls.reopened_at = `athoscail an t-iarratas tarraingthe seo %[2]s` pulls.cmd_instruction_checkout_title = Seiceáil pulls.cmd_instruction_checkout_desc = Ó stór tionscadail, seiceáil brainse nua agus déan tástáil ar na hathruithe. pulls.cmd_instruction_merge_title = Cumaisc diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini index 3e93ee8ba9..411bad835a 100644 --- a/options/locale/locale_hu-HU.ini +++ b/options/locale/locale_hu-HU.ini @@ -932,7 +932,7 @@ issues.close_comment_issue=Hozzászólás és lezárás issues.reopen_issue=Újranyitás issues.reopen_comment_issue=Hozzászólás és újranyitás issues.create_comment=Hozzászólás -issues.commit_ref_at=`hivatkozott erre a hibajegyre egy commit-ból %s` +issues.commit_ref_at=`hivatkozott erre a hibajegyre egy commit-ból %[2]s` issues.role.owner=Tulajdonos issues.role.member=Tag issues.re_request_review=Véleményezés újrakérése diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini index f1a392105e..673d1464b1 100644 --- a/options/locale/locale_id-ID.ini +++ b/options/locale/locale_id-ID.ini @@ -796,7 +796,7 @@ issues.close_comment_issue=Komentar dan Tutup issues.reopen_issue=Buka kembali issues.reopen_comment_issue=Komentar dan Buka Kembali issues.create_comment=Komentar -issues.commit_ref_at=`merujuk masalah dari komit %s` +issues.commit_ref_at=`merujuk masalah dari komit %[2]s` issues.role.owner=Pemilik issues.role.member=Anggota issues.sign_in_require_desc=Masuk untuk bergabung dengan percakapan ini. diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini index baf8286923..9b1d56fed9 100644 --- a/options/locale/locale_is-IS.ini +++ b/options/locale/locale_is-IS.ini @@ -805,8 +805,8 @@ issues.close_comment_issue=Senda ummæli og Loka issues.reopen_issue=Enduropna issues.reopen_comment_issue=Senda ummæli og Enduropna issues.create_comment=Senda Ummæli -issues.closed_at=`lokaði þessu vandamáli %s` -issues.reopened_at=`enduropnaði þetta vandamál %s` +issues.closed_at=`lokaði þessu vandamáli %[2]s` +issues.reopened_at=`enduropnaði þetta vandamál %[2]s` issues.ref_reopened_from=`enduropnaði þetta vandamál %[4]s %[2]s` issues.author=Höfundur issues.role.owner=Eigandi diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index d46f709cde..48995e951f 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -54,7 +54,7 @@ mirror=Mirror new_repo=Nuovo repository new_migrate=Nuova migrazione new_mirror=Nuovo mirror -new_fork=Nuova biforcazione +new_fork=Nuova derivazione new_org=Nuova organizzazione new_project=Nuovo progetto manage_org=Gestisci le organizzazioni @@ -143,12 +143,12 @@ confirm_delete_selected = Confermare l'eliminazione di tutti gli elementi selezi sign_in_with_provider = Accedi con %s new_project_column = Nuova colonna toggle_menu = Mostra/Nascondi menu -filter.not_fork = Non biforcazioni +filter.not_fork = Non fork filter = Filtro filter.clear = Rimuovi filtri filter.is_archived = Archiviato filter.not_archived = Non archiviato -filter.is_fork = Biforcazioni +filter.is_fork = Da fork filter.is_mirror = Mirror filter.not_mirror = Non mirror filter.is_template = Modelli @@ -209,7 +209,6 @@ table_modal.label.columns = Colonne link_modal.header = Aggiungi collegamento link_modal.url = Url link_modal.description = Descrizione -link_modal.paste_reminder = Suggerimento: se hai già copiato un URL negli appunti, puoi incollarlo direttamente nell’editor per creare un collegamento. [filter] string.asc = A - Z @@ -233,7 +232,6 @@ lightweight_desc=Forgejo ha requisiti minimi bassi e può funzionare su un econo license=Open Source license_desc=Ottieni Forgejo! Partecipa per contribuire a rendere questo progetto ancora più bello. Non aver paura di diventare collaborante! install_desc = Semplicemente avvia l'eseguibile per la tua piattaforma, distribuiscilo con Docker, oppure scarica il pacchetto. -platform_desc = È stato verificato che Forgejo è pienamente compatibile con sistemi operativi liberi, come Linux e FreeBSD, nonché con diverse architetture CPU. Scegli liberamente la piattaforma che preferisci! [install] install=Installazione @@ -398,12 +396,12 @@ go_to = Vai a search.type.tooltip = Tipo di ricerca search.fuzzy.tooltip = Includi anche i risultati che corrispondono parzialmente ai termini di ricerca code_search_results = Risultati di ricerca per "%s" -relevant_repositories_tooltip = I repositori che sono biforcazioni o che non hanno argomento, icona, né descrizione sono nascosti. +relevant_repositories_tooltip = I repositori derivati o che non hanno argomento, icona, né descrizione sono nascosti. relevant_repositories = Sono visibili solo i repositori pertinenti, mostra risultati non filtrati. search.match.tooltip = Includi solo risultati che combaciano perfettamente con i termini di ricerca stars_few = %d stelle -forks_one = %d biforcazioni -forks_few = %d biforcazioni +forks_one = %d fork +forks_few = %d fork stars_one = %d stella [auth] @@ -487,8 +485,6 @@ sign_in_openid = Procedi con OpenID hint_login = Hai già un'utenza? Accedi! hint_register = Non hai un'utenza? Registrati ora. sign_up_button = Registrati ora. -unauthorized_credentials = Le credenziali non sono corrette o sono scadute. Controlla il comando o vedi %s per maggiori informazioni -use_onetime_code = Usa un codice monouso [mail] view_it_on=Visualizza su %s @@ -684,8 +680,6 @@ Location = Posizione AccessToken = Token di accesso FullName = Nome e cognome To = Nome del ramo -email_domain_is_not_allowed = Il dominio dell'indirizzo email dell'utente %s è in conflitto con EMAIL_DOMAIN_ALLOWLIST o EMAIL_DOMAIN_BLOCKLIST. Assicurati di aver inserito correttamente l'indirizzo email. -username_claiming_cooldown = Il nome utente non può essere assegnato, poiché il periodo di attesa non è ancora terminato. Sarà disponibile il %[1]s. [user] @@ -729,7 +723,6 @@ followers.title.one = Seguace followers.title.few = Seguaci following.title.one = Seguito following.title.few = Osservato -public_activity.visibility_hint.self_private_profile = Poiché il tuo profilo è privato, la tua attività è visibile solo a te e agli amministratori dell'istanza. Configura. [settings] @@ -1052,7 +1045,7 @@ added_on = Aggiunto su %s additional_repo_units_hint = Suggerisci l'attivazione di unità aggiuntive nel repositorio update_hints = Aggiorna suggerimenti update_hints_success = I suggerimenti sono stati aggiornati. -additional_repo_units_hint_description = Visualizza un suggerimento “Abilita altro” per i repositori che non hanno tutte le unità disponibili abilitate. +additional_repo_units_hint_description = Mostra un pulsante "Aggiungi più sezioni..." per i repositori che non hanno tutte le sezioni disponibili aggiunte. hints = Suggerimenti pronouns = Pronomi pronouns_custom = Personalizzato @@ -1060,34 +1053,6 @@ pronouns_unspecified = Non specificato language.title = Lingua predefinita language.description = Questa lingua verrà salvata nella tua utenza e verrà usata come predefinita ogni volta che farai l'accesso. language.localization_project = Aiutaci a tradurre Forgejo nella tua lingua! Più informazioni. -quota.sizes.assets.attachments.all = Allegati -quota.rule.no_limit = Illimitato -quota.sizes.assets.attachments.releases = Allegati del rilascio -quota.rule.exceeded = Superato -regenerate_token = Rigenera -access_token_regeneration = Rigenera il token d'accesso -access_token_regeneration_desc = Rigenerare un token comporterà la revoca dell'accesso al tuo account per tutte le applicazioni che lo utilizzano. Questa operazione è irreversibile. Vuoi procedere? -regenerate_token_success = Il token è stato rigenerato. Le applicazioni che lo utilizzano non hanno più accesso alla tua utenza e devono essere aggiornate con il nuovo token. -user_block_yourself = Non puoi bloccare te stesso. -quota.applies_to_user = Le seguenti regole di quota si applicano al tuo account -quota.applies_to_org = Le seguenti regole di quota si applicano a questa organizzazione -quota.rule.exceeded.helper = La dimensione totale degli oggetti per questa regola ha superato la quota. -quota.sizes.all = Tutti -quota.sizes.repos.all = Repositori -quota.sizes.repos.public = Repositori pubblici -quota.sizes.repos.private = Repositori privati -quota.sizes.git.all = Contenuto git -quota.sizes.git.lfs = Git LFS -quota.sizes.assets.all = Risorse -quota.sizes.assets.attachments.issues = Allegati della segnalazione -quota.sizes.assets.artifacts = Artefatti -quota.sizes.assets.packages.all = Pacchetti -quota.sizes.wiki = Wiki -keep_pronouns_private = Mostra i pronomi solo agli utenti che hanno effettuato il login -keep_pronouns_private.description = Questa impostazione nasconderà i tuoi pronomi agli utenti non ancora autenticati. -storage_overview = Panoramica spazio di archiviazione -quota = Quota -change_username_redirect_prompt.with_cooldown.one = Il vecchio nome utente sarà disponibile per tutti dopo un periodo di protezione di %\[1]d giorni. Durante questo periodo di attesa potrai comunque tornare al vecchio nome utente. [repo] owner=Proprietario @@ -1102,10 +1067,10 @@ template_description=I modelli di repositori consentono allɜ utenti di generare visibility=Visibilità visibility_description=Solo il proprietario o i membri dell'organizzazione se hanno diritti, saranno in grado di vederlo. visibility_helper_forced=L'amministratorə del sito impone che i nuovi repositori siano privati. -visibility_fork_helper=(Questa modifica influenzerà la visibilità di tutte le biforcazioni.) +visibility_fork_helper=(Questa modifica influenzerà la visibilità di tutti i fork.) clone_helper=Hai bisogno di aiuto per la clonazione? Visita Help. fork_repo=Deriva repositorio -fork_from=Biforcazione di +fork_from=Deriva da already_forked=Hai già fatto il fork di %s fork_to_different_account=Fai Fork a un account diverso fork_visibility_helper=La visibilità di un repositorio derivato non può essere modificata. @@ -1549,13 +1514,13 @@ issues.close_comment_issue=Commenta e chiudi issues.reopen_issue=Riapri issues.reopen_comment_issue=Commenta e riapri issues.create_comment=Commento -issues.closed_at=`ha chiuso questa segnalazione %s` -issues.reopened_at=`ha riaperto questa segnalazione %s` -issues.commit_ref_at=`ha fatto riferimento a questa segnalazione dal commit %s` -issues.ref_issue_from=`ha fatto riferimento a questa segnalazione %[3]s %[1]s` -issues.ref_pull_from=`ha fatto riferimento a questa richiesta di modifica %[3]s %[1]s` -issues.ref_closing_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[3]s che la chiuderà, %[1]s` -issues.ref_reopening_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[3]s che la riaprirà, %[1]s` +issues.closed_at=`ha chiuso questa segnalazione %[2]s` +issues.reopened_at=`ha riaperto questa segnalazione %[2]s` +issues.commit_ref_at=`ha fatto riferimento a questa segnalazione dal commit %[2]s` +issues.ref_issue_from=`ha fatto riferimento a questa segnalazione %[4]s %[2]s` +issues.ref_pull_from=`ha fatto riferimento a questa richiesta di modifica %[4]s %[2]s` +issues.ref_closing_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[4]s che la chiuderà, %[2]s` +issues.ref_reopening_from=`ha fatto riferimento a questa segnalazione da una richiesta di modifica %[4]s che la riaprirà, %[2]s` issues.ref_closed_from=`chiuso questa segnalazione %[4]s %[2]s` issues.ref_reopened_from=`ha riaperto questa segnalazione %[4]s %[2]s` issues.ref_from=`da %[1]s` @@ -1753,7 +1718,7 @@ pulls.cannot_merge_work_in_progress=Questa richiesta di modifica è contrassegna pulls.still_in_progress=Ancora in corso? pulls.add_prefix=Aggiungi prefisso %s pulls.remove_prefix=Rimuovi il prefisso %s -pulls.data_broken=Questa richiesta di modifica non è valida a causa di informazioni mancanti sulla biforcazione. +pulls.data_broken=Questa richiesta di modifica è rovinata a causa di informazioni mancanti riguardo la derivazione. pulls.files_conflicted=Questa richiesta di modifica va in conflitto con il ramo di destinazione. pulls.is_checking=Verifica dei conflitti di fusione in corso. Riprova tra qualche istante. pulls.is_ancestor=Questo ramo è già incluso nel ramo di destinazione. Non c'è nulla da fondere. @@ -1811,8 +1776,8 @@ pulls.update_branch_rebase=Aggiorna il ramo per cambio base pulls.update_branch_success=Ramo aggiornato con successo pulls.update_not_allowed=Non ti è permesso aggiornare il ramo pulls.outdated_with_base_branch=Questo ramo non è aggiornato con il ramo di base -pulls.closed_at=`ha chiuso questa richiesta di modifica %s` -pulls.reopened_at=`ha riaperto questa richiesta di modifica %s` +pulls.closed_at=`ha chiuso questa richiesta di modifica %[2]s` +pulls.reopened_at=`ha riaperto questa richiesta di modifica %[2]s` pulls.auto_merge_button_when_succeed=(Quando i controlli sono superati) pulls.auto_merge_when_succeed=Unione automatica quando tutti i controlli sono superati @@ -2135,7 +2100,7 @@ settings.event_create_desc=Ramo o etichetta creati. settings.event_delete=Elimina settings.event_delete_desc=Ramo o etichetta eliminati. settings.event_fork=Deriva -settings.event_fork_desc=Creata una biforcazione del repositorio. +settings.event_fork_desc=Repository derivato. settings.event_wiki=Wiki settings.event_release=Release settings.event_release_desc=Release pubblicata, aggiornata o rimossa in una repository. @@ -2172,7 +2137,7 @@ settings.event_pull_request_sync_desc=Pull request sincronizzata. settings.event_package=Pacchetto settings.event_package_desc=Pacchetto creato o eliminato in un repository. settings.branch_filter=Filtro rami -settings.branch_filter_desc=Filtro, scritto come pattern glob, da applicare ai rami per gli eventi di tipo immissione, creazione di rami e rimozione di rami. Se vuoto o *, vengono considerati tutti gli eventi di tutti i rami. Maggiori dettagli sulla sintassi presso %[2]s. Esempi: master, {master,release*}. +settings.branch_filter_desc=Whitelist dei rami per gli eventi di spinta, creazione dei rami e cancellazione dei rami, specificati come modello globo. Se vuoto o *, gli eventi per tutti i rami sono segnalati. Vedi la documentazione %[2]s per la sintassi. Esempi: master, {master,release*}. settings.active=Attivo settings.active_helper=Le informazioni sugli eventi innescati saranno inviate a questo URL del webhook. settings.add_hook_success=Il webhook è stato aggiunto. @@ -2202,8 +2167,8 @@ settings.web_hook_name_packagist=Packagist settings.packagist_username=Nome utente Packagist settings.packagist_api_token=API token settings.packagist_package_url=Url pacchetto pacchetti -settings.deploy_keys=Chiavi di distribuzione -settings.add_deploy_key=Aggiungi chiave di distribuzione +settings.deploy_keys=Dispiega chiavi +settings.add_deploy_key=Aggiungi chiave di dispiego settings.deploy_key_desc=Le deploy key possiedono l'accesso solamente alla lettura di un repository. settings.is_writable=Abilita accesso scrittura settings.is_writable_info=Permetti a questa deploy key di pushare nella repository. @@ -2212,7 +2177,7 @@ settings.title=Titolo settings.deploy_key_content=Contenuto settings.key_been_used=Una deploy key con contenuto identico è già in uso. settings.key_name_used=Esiste già una deploy key con questo nome. -settings.deploy_key_deletion=Rimuovi chiave di distribuzione +settings.deploy_key_deletion=Rimuovi chiave di dispiego settings.deploy_key_deletion_desc=Rimuovere una chiave di distribuzione ne revocherà l'accesso a questo repository. Continuare? settings.deploy_key_deletion_success=La chiave di distribuzione è stata rimossa. settings.branches=Rami @@ -2655,7 +2620,7 @@ issues.filter_type.reviewed_by_you = Revisionati da te projects.edit_success = Il progetto "%s" è stato aggiornato. issues.keyword_search_unavailable = La ricerca per parola chiave non è attualmente disponibile. Contatta l'amministratore del sito. issues.role.collaborator_helper = Quest*utente è statə invitatə a collaborare al progetto. -pulls.commit_ref_at = `ha fatto riferimento a questa richiesta di modifica da un commit %s` +pulls.commit_ref_at = `ha fatto riferimento a questa richiesta di modifica da un commit %[2]s` settings.thread_id = ID della discussione release.title = Titolo del rilascio visibility_helper = Rendi il repositorio privato @@ -2695,7 +2660,7 @@ wiki.page_title = Titolo della pagina wiki.page_content = Contenuto della pagina settings.mirror_settings.pushed_repository = Repositorio immesso settings.mirror_settings.push_mirror.edit_sync_time = Modifica intervallo di sincronizzazione degli specchi -settings.units.units = Sezioni del repositorio +settings.units.units = Unità della repository settings.units.add_more = Aggiungi ancora... settings.wiki_globally_editable = Consenti a tutti di modificare la wiki settings.pull_mirror_sync_in_progress = Prelevando cambiamenti dal progetto remoto %s. @@ -2767,7 +2732,7 @@ pulls.merged_title_desc_one = ha fuso %[1]d commit da %[2]s in Accedi per creare una richiesta di modifica. -settings.mirror_settings.push_mirror.none_ssh = Nessuno -sync_fork.branch_behind_one = Questo ramo è indietro di %[1]d commit rispetto a %[2]s -sync_fork.branch_behind_few = Questo ramo è indietro di %[1]d commit rispetto a %[2]s -no_eol.text = Nessun fine linea -no_eol.tooltip = Questo file non contiene un carattere di fine linea finale. -milestones.filter_sort.name = Nome -settings.protect_new_rule = Crea una nuova regola di protezione dei rami -editor.commit_email = E-mail di commit -mirror_public_key = Chiave SSH pubblica -mirror_denied_combination = Non è possibile utilizzare contemporaneamente l'autenticazione tramite chiave pubblica e password. -release.type_attachment = Allegato -release.invalid_external_url = URL esterno invalido: "%s" -new_from_template = Utilizza un modello -new_from_template_description = Puoi selezionare un modello di repositorio esistente su questa istanza e applicare le sue impostazioni. -new_advanced = Impostazioni avanzate -new_advanced_expand = Clicca per espandere -summary_card_alt = Scheda riepilogativa del repository %s -issues.filter_sort.relevance = Rilevanza -issues.num_reviews_one = %d revisioni -issues.num_reviews_few = %d revisioni -issues.reaction.add = Aggiungi reazione -issues.reaction.alt_many = %[1] e altri %[2]d hanno reagito %[3]s. -issues.reaction.alt_remove = Rimuovi la reazione %[1]s dal commento. -issues.reaction.alt_add = Aggiungi la reazione %[1]s al commento. -issues.review.remove_review_requests = rimosso richieste di revisione per %\[1]s %\[2]s -comment.blocked_by_user = Non è possibile commentare perché sei stato bloccato dal proprietario del repositorio o dall'autore. -issues.summary_card_alt = Scheda riepilogativa di una segnalazione intitolata "%s" nel repositorio %s -pulls.delete_after_merge.head_branch.is_default = Il ramo head che desideri eliminare è il ramo predefinito e non può essere eliminato. -settings.event_action_success = Successo -settings.event_action_success_desc = L'esecuzione dell'azione è andata a buon fine. -diff.git-notes.remove-header = Rimuovi nota -diff.git-notes.remove-body = Questa nota verrà rimossa. -activity.commit = Attività di commit [graphs] contributors.what = contribuzioni @@ -2947,7 +2839,7 @@ team_name_helper=I nomi dei team devono essere brevi e semplici da ricordare. team_desc_helper=Descrivi lo scopo o il ruolo del team. team_access_desc=Accesso al repository team_permission_desc=Autorizzazione -team_unit_desc=Consenti l'accesso alle sezioni del repositorio +team_unit_desc=Consenti l'accesso a sezioni di progetto team_unit_disabled=(Disabilitato) form.create_org_not_allowed=Non disponi dell'autorizzazione per creare un organizzazione. @@ -3601,12 +3493,6 @@ config.cache_test_slow = Successo nel controllo della cache, ma la risposta è l config.app_slogan = Slogan dell'istanza auths.default_domain_name = Nome di dominio predefinito utilizzato per l'indirizzo e-mail users.restricted.description = Permetti di interagire solo con i repositori e le organizzazioni in cui l'utente è aggiuntə come collaborante. Ciò evita l'accesso ai repositori pubblici di quest'istanza. -emails.deletion_success = L'indirizzo e-mail è stato eliminato. -monitor.duration = Durata (s) -emails.delete_desc = Confermare l’eliminazione di questo indirizzo email? -emails.delete_primary_email_error = Non puoi eliminare la e-mail primaria. -emails.delete = Elimina e-mail -users.organization_creation.description = Abilita la creazione di nuove organizzazioni. [action] @@ -3851,31 +3737,6 @@ owner.settings.cargo.initialize.success = L'indice di Cargo è stato creato corr owner.settings.cargo.rebuild.no_index = Impossibile ricostruire, nessun indice è inizializzato. owner.settings.cargo.rebuild.description = La ricostruzione può essere utile se l'indice non è sincronizzato con i pacchetti Cargo conservati. npm.dependencies.bundle = Dipendenze raggruppate -arch.version.groups = Gruppo -arch.version.conflicts = Va in conflitto con -arch.version.depends = Dipende da -arch.version.makedepends = Dipendenze di build -arch.version.checkdepends = Dipendenze di controllo -arch.version.replaces = Sostituisce -arch.version.optdepends = Dipende opzionalmente da -arch.version.backup = Backup -search_in_external_registry = Cerca in %s -arch.version.provides = Fornisce -arch.pacman.conf = Aggiungi il server con la relativa distribuzione e architettura a /etc/pacman.conf: -alt.setup = Aggiungi il repositorio alla lista dei repositori in rete (seleziona l'architettura necessaria al posto di "_arch_"): -container.images.title = Immagini -arch.version.properties = Proprietà della versione -alt.registry.install = Per installare il pacchetto, esegui il comando seguente: -alt.install = Installa pacchetto -alt.registry = Configura questo registro dalla riga di comando: -arch.pacman.helper.gpg = Aggiungi il certificato a pacman: -arch.pacman.repo.multi = %s ha la stessa versione in diverse distribuzioni. -arch.pacman.repo.multi.item = Configurazione per %s -arch.pacman.sync = Sincronizza il paccketto con pacman: -arch.version.description = Descrizione -alt.repository = Informazioni del repositorio -alt.repository.architectures = Architetture -alt.repository.multiple_groups = Questo pacchetto è disponibile per più gruppi. [secrets] secrets = Segreti @@ -3973,7 +3834,7 @@ runs.empty_commit_message = (messaggio di commit vuoto) runs.no_runs = Il flusso di lavoro non è stato ancora eseguito. variables.creation.success = La variabile "%s" è stata aggiunta. variables.description = Le variabili saranno passate a determinate azioni e non possono essere lette altrimenti. -need_approval_desc = È necessaria l'approvazione per eseguire flussi di lavoro per richieste di modifica da biforcazioni. +need_approval_desc = È necessaria l'approvazione per eseguire flussi di lavoro per richieste di modifica da derivazioni. runs.no_workflows.documentation = Per ulteriori informazioni sulle Forgejo Actions vedi la documentazione. runs.no_workflows.quick_start = Non sai come iniziare con le Forgejo Actions? Vedi la guida rapida. runners.delete_runner_notice = Se un'attività è in esecuzione su questo esecutore sarà terminata ed etichettata fallito. Potrebbe rompere flussi di lavoro di costruzione. @@ -3987,8 +3848,6 @@ workflow.dispatch.invalid_input_type = Tipo ingresso "%s" non valido. workflow.dispatch.warn_input_limit = Visualizzati solo i primi %d ingressi. runs.no_job = Il flusso di lavoro deve contenere almeno un incarico workflow.dispatch.use_from = Usa flusso di lavoro da -variables.not_found = Non è stato possibile trovare la variabile. -runs.expire_log_message = I log sono stati eliminati in quanto troppo vecchi. @@ -3997,7 +3856,6 @@ runs.expire_log_message = I log sono stati eliminati in quanto troppo vecchi. type-3.display_name = Progetto dell'organizzazione type-1.display_name = Progetto individuale type-2.display_name = Progetto -deleted.display_name = Progetto eliminato [git.filemode] symbolic_link=Link Simbolico @@ -4038,7 +3896,6 @@ milestone_kind = Ricerca tappe... regexp_tooltip = Interpreta i termini di ricerca come un'espressione regolare regexp = Espressione Regolare union_tooltip = Include i risultati che combaciano con una qualsiasi delle parole chiave separata da spazi -union = Parole chiavi [munits.data] gib = GiB @@ -4057,16 +3914,4 @@ filepreview.line = Linea %[1]d in %[2]s [repo.permissions] issues.write = Scrittura: Chiudere segnalazioni e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze. -pulls.write = Scrittura: Chiudere richieste di modifica e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze. -releases.write = Scrittura: Può pubblicare, modificare ed eliminare rilasci e le risorse ad essi allegate. -code.write = Scrittura: Può aggiungere commit al repositorio, creare rami ed etichette. -wiki.read = Lettura: Può leggere la wiki integrata e la sua cronologia. -releases.read = Lettura: Può visualizzare e scaricare i rilasci. -projects.read = Lettura: Può accedere alle board di progetto del repositorio. -code.read = Lettura: Può accedere e clonare il codice del repositorio. -wiki.write = Scrittura: Può creare, aggiornare ed eliminare pagine nella wiki integrata. -issues.read = Lettura: Può leggere e creare segnalazioni e commenti. -pulls.read = Lettura: Può leggere e creare richieste di modifica. - -[translation_meta] -test = daje Roma \ No newline at end of file +pulls.write = Scrittura: Chiudere richieste di modifica e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze. \ No newline at end of file diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 555f5c6a75..d4d7024f5d 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -1610,13 +1610,13 @@ issues.close_comment_issue=コメントしてクローズ issues.reopen_issue=再オープンする issues.reopen_comment_issue=コメントして再オープン issues.create_comment=コメントする -issues.closed_at=`がイシューをクローズ %s` -issues.reopened_at=`がイシューを再オープン %s` -issues.commit_ref_at=`がコミットでこのイシューを参照 %s` -issues.ref_issue_from=`が%[3]s、このイシューを参照 %[1]s` -issues.ref_pull_from=`が%[3]s、このプルリクエストを参照 %[1]s` -issues.ref_closing_from=`が%[3]s、プルリクエストがこのイシューをクローズするよう参照 %[1]s` -issues.ref_reopening_from=`が%[3]s、プルリクエストがこのイシューを再オープンするよう参照 %[1]s` +issues.closed_at=`がイシューをクローズ %[2]s` +issues.reopened_at=`がイシューを再オープン %[2]s` +issues.commit_ref_at=`がコミットでこのイシューを参照 %[2]s` +issues.ref_issue_from=`が%[4]s、このイシューを参照 %[2]s` +issues.ref_pull_from=`が%[4]s、このプルリクエストを参照 %[2]s` +issues.ref_closing_from=`が%[4]s、プルリクエストがこのイシューをクローズするよう参照 %[2]s` +issues.ref_reopening_from=`が%[4]s、プルリクエストがこのイシューを再オープンするよう参照 %[2]s` issues.ref_closed_from=`が%[4]s、このイシューをクローズ %[2]s` issues.ref_reopened_from=`が%[4]s、このイシューを再オープン %[2]s` issues.ref_from=` %[1]s にて` @@ -1923,8 +1923,8 @@ pulls.update_branch_success=ブランチの更新が成功しました pulls.update_not_allowed=ブランチを更新する権限がありません pulls.outdated_with_base_branch=このブランチはベースブランチに対して最新ではありません pulls.close=プルリクエストをクローズ -pulls.closed_at=`がプルリクエストをクローズ %s` -pulls.reopened_at=`がプルリクエストを再オープン %s` +pulls.closed_at=`がプルリクエストをクローズ %[2]s` +pulls.reopened_at=`がプルリクエストを再オープン %[2]s` pulls.cmd_instruction_hint=コマンドラインの手順を表示 pulls.cmd_instruction_checkout_title=チェックアウト pulls.cmd_instruction_checkout_desc=プロジェクトリポジトリから新しいブランチをチェックアウトし、変更内容をテストします。 @@ -2721,7 +2721,7 @@ settings.wiki_rename_branch_main = wikiのブランチ名を正規化する settings.wiki_rename_branch_main_desc = wikiによって内部的に使われているブランチ名を "%s" に変更します。これは恒久的で元に戻すことはできません。 contributors.contribution_type.additions = 追加 vendored = vendor済み -pulls.commit_ref_at = `このプルリクエストを言及するコミット %s` +pulls.commit_ref_at = `このプルリクエストを言及するコミット %[2]s` pulls.fast_forward_only_merge_pull_request = Fast-forwardのみ admin.manage_flags = フラグ管理 admin.update_flags = フラグを更新 diff --git a/options/locale/locale_jbo.ini b/options/locale/locale_jbo.ini index 947bb298de..6124dc4d22 100644 --- a/options/locale/locale_jbo.ini +++ b/options/locale/locale_jbo.ini @@ -2,12 +2,4 @@ [common] -home = zdani -dashboard = jitypalna -explore = sisku -help = se sidju -logo = se'isni -sign_in = co'a nerkla -sign_in_with_provider = co'a nerka sepi'o la .%s. -sign_out = co'a cliva -sign_up = co'a gumri \ No newline at end of file +home = zdani \ No newline at end of file diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index be0400bea4..433ec01828 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -943,7 +943,7 @@ issues.close_comment_issue=클로즈 및 코멘트 issues.reopen_issue=다시 열기 issues.reopen_comment_issue=다시 오픈 및 코멘트 issues.create_comment=코멘트 -issues.commit_ref_at=` 커밋 %s에서 이 이슈 언급` +issues.commit_ref_at=` 커밋 %[2]s에서 이 이슈 언급` issues.role.owner=소유자 issues.role.member=멤버 issues.sign_in_require_desc=로그인하여 이 대화에 참여하세요. @@ -1378,7 +1378,7 @@ issues.closed_by_fake = %[2]s님이 %[1]s에 닫음 issues.new.closed_projects = 닫힌 프로젝트 pulls.merged_by_fake = %[2]s님이 %[1]s 병합함 issues.closed_by = %[3]s님이 %[1]s에 닫음 -issues.closed_at = `%s`에 이 이슈를 닫음 +issues.closed_at = `%[2]s`에 이 이슈를 닫음 issues.filter_milestone_closed = 닫힌 마일스톤 issues.opened_by_fake = %[2]s님이 %[1]s에 열음 issues.filter_project_none = 프로젝트 없음 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 4a98e1aa9d..789871f3c3 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -1577,7 +1577,7 @@ issues.remove_ref_at=`noņēma atsauci no %s %s` issues.add_ref_at=`pievienoja atsauci uz %s %s` issues.delete_branch_at=`izdzēsa zaru %s %s` issues.filter_label=Iezīme -issues.filter_label_exclude=Jāizmanto Alt + klikšķis, lai neiekļautu iezīmes +issues.filter_label_exclude=`Jāizmanto alt + klikšķis/Enter, lai neiekļautu iezīmes` issues.filter_label_no_select=Visas iezīmes issues.filter_label_select_no_label=Bez iezīmes issues.filter_milestone=Atskaites punkts @@ -1651,13 +1651,13 @@ issues.close_comment_issue=Aizvērt ar piebildi issues.reopen_issue=Atvērt atkārtoti issues.reopen_comment_issue=Atkārtoti atvērt ar piebildi issues.create_comment=Pievienot piebildi -issues.closed_at=`aizvēra šo pieteikumu %s` -issues.reopened_at=`atkārtoti atvēra šo pieteikumu %s` -issues.commit_ref_at=`atsaucās uz šo pieteikumu iesūtījumā %s` -issues.ref_issue_from=`atsaucās uz šo pieteikumu %[3]s %[1]s` -issues.ref_pull_from=`atsaucās uz šo izmaiņu pieprasījumu %[3]s %[1]s` -issues.ref_closing_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[3]s, kas aizvērs to, %[1]s` -issues.ref_reopening_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[3]s, kas atkārtoti atvērs to, %[1]s` +issues.closed_at=`aizvēra šo pieteikumu %[2]s` +issues.reopened_at=`atkārtoti atvēra šo pieteikumu %[2]s` +issues.commit_ref_at=`atsaucās uz šo pieteikumu iesūtījumā %[2]s` +issues.ref_issue_from=`atsaucās uz šo pieteikumu %[4]s %[2]s` +issues.ref_pull_from=`atsaucās uz šo izmaiņu pieprasījumu %[4]s %[2]s` +issues.ref_closing_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[4]s, kas aizvērs to, %[2]s` +issues.ref_reopening_from=`atsaucās uz šo pieteikumu izmaiņu pieprasījumā %[4]s, kas atkārtoti atvērs to, %[2]s` issues.ref_closed_from=`aizvēra pieteikumu %[4]s %[2]s` issues.ref_reopened_from=`atkārtoti atvēra pieteikumu %[4]s %[2]s` issues.ref_from=`no %[1]s` @@ -1964,8 +1964,8 @@ pulls.update_branch_success=Zara atjaunināšana bija sekmīga pulls.update_not_allowed=Nav ļauts atjaunināt zaru pulls.outdated_with_base_branch=Šis zars ir novecojis salīdzinājumā ar pamata zaru pulls.close=Aizvērt izmaiņu pieprasījumu -pulls.closed_at=`aizvēra šo izmaiņu pieprasījumu %s` -pulls.reopened_at=`atkārtoti atvēra šo izmaiņu pieprasījumu %s` +pulls.closed_at=`aizvēra šo izmaiņu pieprasījumu %[2]s` +pulls.reopened_at=`atkārtoti atvēra šo izmaiņu pieprasījumu %[2]s` pulls.cmd_instruction_hint=Apskatīt komandrindas izmantošanas norādes pulls.cmd_instruction_checkout_title=Paņemt pulls.cmd_instruction_checkout_desc=Projekta glabātavā jāizveido jauns zars un jāpārbauda izmaiņas. @@ -2826,7 +2826,7 @@ issues.author.tooltip.pr = Šis lietotājs ir šī izmaiņu pieprasījuma izveid pulls.edit.already_changed = Neizdevās saglabāt izmaiņu pieprasījuma izmaiņas. Izskatās, ka saturu jau ir mainījis kāds cits lietotājs. Lūgums atsvaidzināt lapu un mēģināt labot vēlreiz, lai izvairītos no izmaiņu pārrakstīšanas pulls.blocked_by_user = Tu nevari izveidot izmaiņu pieprasījumu šajā glabātavā, jo tās īpašnieks ir Tevi liedzis. issues.all_title = Visi -pulls.commit_ref_at = ` atsaucās uz šo izmaiņu pieprasījumu iesūtījumā %s` +pulls.commit_ref_at = ` atsaucāš uz šo izmaiņu pieprasījumu iesūtījumā %[2]s` issues.num_participants_one = %d dalībnieks pulls.title_desc_one = vēlas iekļaut %[1]d iesūtījumu no %[2]s %[3]s issues.archived_label_description = (Arhivēts) %s diff --git a/options/locale/locale_nb_NO.ini b/options/locale/locale_nb_NO.ini index 59673fd4e3..2c8b5cfc64 100644 --- a/options/locale/locale_nb_NO.ini +++ b/options/locale/locale_nb_NO.ini @@ -60,7 +60,7 @@ rerun = Kjør på nytt rerun_all = Kjør alle jobber på nytt save = Lagre cancel = Avbryt -forks = Kopier +forks = Forks milestones = Milepæler ok = OK test = Test @@ -133,42 +133,14 @@ webauthn_error_duplicated = Sikkerhetsnøkkelen er ikke tillatt for denne foresp webauthn_error_timeout = Et tidsavbrudd oppsto før nøkkelen din kunne leses. Vennligst last inn siden på nytt og prøv igjen. new_fork = Ny fork av repository collaborative = Samarbeidende -error413 = Du har brukt opp kvoten din. -issues = Saker -unpin = Løsne -filter.is_fork = Forks -filter.not_fork = Ikke forks -pull_requests = Pull requests -copy_branch = Kopier branch navn -error404 = Siden du forsøker å nå eksisterer ikke, er blitt fjernet eller du har ikke tilgang til å se den. -tracked_time_summary = Oppsummering av sporet tid basert på problemfiltre [search] -search = Søk… +search = Søk... type_tooltip = Søketype fuzzy = Fuzzy union = Union regexp = RegExp exact = Nøyaktig -team_kind = Søk i teams… -code_kind = Søk i kode… -package_kind = Søk i pakker… -project_kind = Søk i prosjekter… -branch_kind = Søk i brancher… -commit_kind = Søk i commits… -regexp_tooltip = Tolk søkeordet som et regulæruttrykk -pull_kind = Søk i pulls… -keyword_search_unavailable = Søk etter nøkkelord er for øyeblikket ikke tilgjengelig. Kontakt administratoren. -exact_tooltip = Inkluder kun resultater som samsvarer nøyaktig med søkeordet -repo_kind = Søk i repositorer… -fuzzy_tooltip = Inkluder resultater som også stemmer godt overens med søketermen -org_kind = Søk i organisasjoner… -issue_kind = Søk i saker… -runner_kind = Søk i runners… -no_results = Ingen treff funnet. -union_tooltip = Inkluder resultater som samsvarer med ett eller flere av nøkkelordene adskilt med mellomrom -code_search_unavailable = Kodesøk er ikke tilgjengelig. Kontakt administratoren. -user_kind = Søk i brukere… [auth] verify = Bekreft @@ -180,88 +152,4 @@ oauth_signup_title = Fullfør ny konto oauth_signup_submit = Fullfør konto [home] -uname_holder = Brukernavn eller e-postadresse - -[heatmap] -contributions_zero = Ingen bidrag -number_of_contributions_in_the_last_12_months = %s bidrag de siste 12 månedene -contributions_one = bidrag -contributions_format = {contributions} den {day} {month} {year} -less = Mindre -contributions_few = bidrag -more = Mer - -[editor] -buttons.heading.tooltip = Legg til overskrift -buttons.bold.tooltip = Legg til uthevet tekst -buttons.italic.tooltip = Legg til kursiv text -buttons.list.unordered.tooltip = Legg til punktliste -buttons.list.ordered.tooltip = Legg til nummerert liste -buttons.link.tooltip = Legg til link -buttons.quote.tooltip = Siter tekst -buttons.mention.tooltip = Nevn en bruker eller team -buttons.list.task.tooltip = Legg til liste over saker -buttons.code.tooltip = Legg til kode -table_modal.header = Legg til tabell -table_modal.placeholder.header = Overskrift -table_modal.placeholder.content = Innhold -table_modal.label.columns = Kolonner -buttons.new_table.tooltip = Legg til tabell -table_modal.label.rows = Rader -buttons.switch_to_legacy.tooltip = Bruk den gamle editoren istedenfor -buttons.disable_monospace_font = Deaktiver monospace font -buttons.ref.tooltip = Referanse til en sak eller pull request -buttons.indent.tooltip = Grupper elementene med et nivå -buttons.unindent.tooltip = Pakk ut elementene med et nivå -link_modal.url = Url -link_modal.description = Beskrivelse -link_modal.header = Legg til en link -buttons.enable_monospace_font = Aktiver monospace font -link_modal.paste_reminder = Tips: Når du har en URL i utklippstavlen kan du lime den direkte inn i editoren for å lage en lenke. - -[aria] -footer = Bunntekst -navbar = Navigasjonslinje -footer.links = Linker -footer.software = Om dette programmet - -[filter] -string.asc = A - Z -string.desc = Z - A - -[error] -occurred = En feil oppstod -not_found = Kunne ikke finne målet. -report_message = Hvis du mener dette er en feil i Forgejo kan du søke på Codeberg eller åpne en ny sak. -network_error = Nettverks feil -server_internal = Intern server feil - -[install] -docker_helper = Dersom du bruker Forgejo med Docker, anbefales det å lese dokumentasjonen før du gjør endringer i konfigurasjonen. -db_title = Database innstillinger -require_db_desc = Forgejo krever MySQL, PostgreSQL, SQLite3 eller TiDB (MySQL protokoll). -db_type = Database type -password = Passord -user = Brukernavn -install = Installasjon -title = Førstegangsoppsett -host = Server -db_name = Database navn -db_schema = Skjema -db_schema_helper = La stå tomt for databasens standardverdi ("public"). -ssl_mode = SSL -path = Sti -sqlite_helper = Sti til SQLite3-databasen.
Bruk absolutt filsti dersom Forgejo kjøres som en tjeneste. -reinstall_error = Du prøver å installere i en eksisterende Forgejo-database -reinstall_confirm_message = Å installere på nytt med en eksisterende Forgejo-database kan føre til problemer. I de fleste tilfeller bør du bruke din eksisterende "app.ini" for å kjøre Forgejo. Hvis du vet hva du gjør, og vil fortsette, bekreft følgende: - -[startpage] -install = Enkel å installere -platform = Plattformuavhengig -install_desc = Du kan enkelt kjøre programfilen for din platform, bruke Docker, eller hente den som en ferdig pakke. -lightweight_desc = Forgejo krever lite ressurser og kan kjøres på en rimelig Raspberry Pi. Spar strøm og miljøet! -app_desc = En enkel Git-tjeneste du kan drifte selv -lightweight = Lettvekt -license = Åpen kildekode -platform_desc = Forgejo fungerer på frie operativsystemer som Linux og FreeBSD, og støtter flere CPU-arkitekturer. Velg den plattformen du foretrekker! -license_desc = Last ned Forgejo! Bli med ved å bidra for å gjøre prosjektet enda bedre. Ikke vær redd for å bli en bidragsyter! \ No newline at end of file +uname_holder = Brukernavn eller e-postadresse \ No newline at end of file diff --git a/options/locale/locale_nds.ini b/options/locale/locale_nds.ini index cd91f7c35a..57985942ed 100644 --- a/options/locale/locale_nds.ini +++ b/options/locale/locale_nds.ini @@ -1347,7 +1347,7 @@ issues.change_title_at = `hett %[3]s de Titel vun %[1]s issues.change_ref_at = `hett %[3]s de Nömen vun %[1]s to %[2]s ännert` issues.delete_branch_at = `hett %[2]s de Twieg %[1]s lösket` issues.filter_label = Vermark -issues.filter_label_exclude = Bruuk Alt + Klick, um Vermarkens uttosluten +issues.filter_label_exclude = `Bruuk Alt+Klick/Enter, um Vermarkens uttosluten` issues.filter_label_no_select = All Vermarkens issues.filter_label_select_no_label = Keen Vermark issues.filter_milestone = Marksteen @@ -1434,12 +1434,12 @@ issues.comment_pull_merged_at = hett Kommitteren %[1]s in %[2]s %[3]s tosamenfö issues.close_comment_issue = Mit Kommentaar dichtmaken issues.reopen_comment_issue = Mit Kommentaar weer opmaken issues.create_comment = Kommenteren -issues.reopened_at = `hett deeses Gefall %s weer opmaakt` +issues.reopened_at = `hett deeses Gefall %[2]s weer opmaakt` issues.comment_manually_pull_merged_at = hett Kommitteren %[1]s in %[2]s %[3]s vun Hand tosamenföhrt issues.reopen_issue = Weer opmaken -issues.closed_at = `hett deeses Gefall %s dichtmaakt` -issues.commit_ref_at = `hett deeses Gefall %s vun eenem Kommitteren benöömt` -issues.ref_closing_from = `hett deeses Gefall %[1]s vun eenem Haalvörslag, wat ’t %[3]s dichtmaken word, benöömt` +issues.closed_at = `hett deeses Gefall %[2]s dichtmaakt` +issues.commit_ref_at = `hett deeses Gefall %[2]s vun eenem Kommitteren benöömt` +issues.ref_closing_from = `hett deeses Gefall %[2]s vun eenem Haalvörslag, wat ’t %[4]s dichtmaken word, benöömt` issues.ref_closed_from = `hett deeses Gefall %[4]s %[2]s dichtmaakt` issues.ref_reopened_from = `hett deeses Gefall %[4]s %[2]s weer opmaakt` issues.ref_from = `vun %[1]s` @@ -1477,12 +1477,12 @@ issues.label.filter_sort.reverse_alphabetically = Umdreiht na de Alphabeet issues.label.filter_sort.by_size = Lüttste Grött issues.num_participants_one = %d Mitmaker issues.num_participants_few = %d Mitmakers -issues.ref_pull_from = `hett deesen Haalvörslag %[3]s %[1]s benöömt` +issues.ref_pull_from = `hett deesen Haalvörslag %[4]s %[2]s benöömt` issues.label_title = Naam issues.label_archived_filter = Archiveert Vermarkens wiesen issues.archived_label_description = (Archiveert) %s -issues.ref_issue_from = `hett deeses Gefall %[3]s %[1]s benöömt` -issues.ref_reopening_from = `hett deeses Gefall vun eenem Haalvörslag, wat ’t %[3]s weer opmaken word, %[1]s benöömt` +issues.ref_issue_from = `hett deeses Gefall %[4]s %[2]s benöömt` +issues.ref_reopening_from = `hett deeses Gefall vun eenem Haalvörslag, wat ’t %[4]s weer opmaken word, %[2]s benöömt` issues.author.tooltip.issue = Deeser Bruker is de Autor vun deesem Gefall. issues.role.member_helper = Deeser Bruker is een Liddmaat vun de Vereenigung, wat de Eegner vun deesem Repositorium is. issues.role.collaborator_helper = Deeser Bruuker is inladen worden, in deesem Repositorium mittoarbeiden. @@ -1552,7 +1552,7 @@ issues.dependency.pr_close_blocks = Deeser Haalvörslag blockeert dat Dichtmaken issues.dependency.issue_batch_close_blocked = Kann de utköört Gefallens nich all tosamen dichtmaken, denn Gefall #%d hett noch open Ofhangens issues.dependency.pr_close_blocked = Du muttst all Gefallens, wat deesen Haalvörslag blockeren, dichtmaken, ehr du dat hier tosamenföhren kannst. issues.dependency.blocks_short = Blockeert -issues.dependency.blocked_by_short = Hangt of vun +issues.dependency.blocked_by_short = Hang of vun issues.dependency.remove_header = Ofhangen wegdoon issues.dependency.setting = Ofhangens för Gefallens un Haalvörslagen anknipsen issues.dependency.add_error_same_issue = Du kannst een Gefall nich vun sik sülvst ofhangen laten. @@ -1740,8 +1740,8 @@ pulls.status_checks_show_all = All Överprüfens wiesen pulls.update_branch_rebase = Twieg mit Umbaseren vernejen pulls.outdated_with_base_branch = De Twieg is tegen de Grund-Twieg verollt pulls.close = Haalvörslag dichtmaken -pulls.closed_at = `hett deesen Haalvörslag %s dichtmaakt` -pulls.reopened_at = `hett deesen Haalvörslag %s weer opmaakt` +pulls.closed_at = `hett deesen Haalvörslag %[2]s dichtmaakt` +pulls.reopened_at = `hett deesen Haalvörslag %[2]s weer opmaakt` pulls.cmd_instruction_hint = Wies Oorderreeg-Instruksjes pulls.cmd_instruction_checkout_title = Utchecken pulls.cmd_instruction_merge_title = Tosamenföhren @@ -1771,7 +1771,7 @@ milestones.deletion = Marksteen lösken pulls.has_merged = Fehlslagen: De Haalvörslag is tosamenföhrt worden, du kannst nich noch eenmaal tosamenföhren of de Enn-Twieg ännern. pulls.unrelated_histories = Tosamenföhren fehlslagen: De Tosamenföhrens-Kopp un -Grund hebben keene gemeensame Histoorje. Wenk: Versöök eene anner Tosamenföhrens-Aard pulls.update_not_allowed = Du düürst deesen Twieg nich vernejen -pulls.commit_ref_at = `hett deesen Haalvörslag %s vun eenem Kommitteren benöömt` +pulls.commit_ref_at = `hett deesen Haalvörslag %[2]s vun eenem Kommitteren benöömt` pulls.auto_merge_newly_scheduled = De Haalvörslag weer sett, sik tosamentoföhren, wenn all Överprüfens kumpleet sünd. milestones.clear = Leeg maken pulls.push_rejected_no_message = Schuven fehlslagen: Dat Schuven is sünner feerne Naricht oflehnt worden. Bidde överprüüf de Git-Hakens för deeses Repositorium diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index 7e08c8036c..549718ce23 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -1495,7 +1495,7 @@ issues.remove_ref_at=`heeft referentie %s verwijderd %s` issues.add_ref_at=`heeft referentie %s toegevoegd %s` issues.delete_branch_at=`heeft %[2]s de branch %[1]s verwijderd.` issues.filter_label=Label -issues.filter_label_exclude=Gebruik alt + klik om labels uit te sluiten +issues.filter_label_exclude=Gebruik alt + klik/voer in om labels uit te sluiten issues.filter_label_no_select=Alle labels issues.filter_milestone=Mijlpaal issues.filter_project=Project @@ -1554,13 +1554,13 @@ issues.close_comment_issue=Sluit met commentaar issues.reopen_issue=Heropen issues.reopen_comment_issue=Heropen met commentaar issues.create_comment=Reageer -issues.closed_at=`heeft deze issue gesloten %s` -issues.reopened_at=`heropende deze issue %s` -issues.commit_ref_at=`verwees naar dit probleem vanuit commit %s` -issues.ref_issue_from=`refereerde aan dit issue %[3]s %[1]s` -issues.ref_pull_from=`refereerde aan deze pull request %[3]s %[1]s` -issues.ref_closing_from=`verwees naar deze issue van een pull request %[3]s dat het zal sluiten, %[1]s` -issues.ref_reopening_from=`verwees naar een pull request %[3]s dat dit issue heropent %[1]s ` +issues.closed_at=`heeft dit probleem gesloten %[2]s` +issues.reopened_at=`heropende dit probleem %[2]s` +issues.commit_ref_at=`verwees naar dit probleem vanuit commit %[2]s'` +issues.ref_issue_from=`refereerde aan dit issue %[4]s %[2]s` +issues.ref_pull_from=`refereerde aan deze pull request %[4]s %[2]s` +issues.ref_closing_from=`verwees naar deze issue van een pull request %[4]s dat het zal sluiten, %[2]s` +issues.ref_reopening_from=`verwees naar een pull request %[4]s dat dit issue heropent %[2]s ` issues.ref_closed_from=`sloot dit issue %[4]s %[2]s` issues.ref_reopened_from=`heropende dit issue %[4]s %[2]s` issues.ref_from=`van %[1]s` @@ -1815,8 +1815,8 @@ pulls.update_branch_rebase=Update branch via herbaseren pulls.update_branch_success=Branch update is geslaagd pulls.update_not_allowed=Je hebt geen toestemming om branch bij te werken pulls.outdated_with_base_branch=Deze branch is verouderd met de basis branch -pulls.closed_at=`heeft deze pull request gesloten %s` -pulls.reopened_at=`heropende deze pull request %s` +pulls.closed_at=`heeft deze pull request gesloten %[2]s` +pulls.reopened_at=`heropende deze pull request %[2]s` pulls.auto_merge_button_when_succeed=(Bij geslaagde controles) pulls.auto_merge_when_succeed=Automatisch samenvoegen wanneer alle controles gelukt zijn @@ -2627,7 +2627,7 @@ projects.column.set_default_desc = Stel deze kolom in als standaard voor ongecat issues.action_check = Aanvinken/uitvinken issues.dependency.issue_batch_close_blocked = Het is niet mogelijk om de issues die u gekozen heeft in bulk te sluiten, omdat issue #%d nog open afhankelijkheden heeft pulls.review_only_possible_for_full_diff = Beoordeling is alleen mogelijk bij het bekijken van de volledige diff -pulls.commit_ref_at = `heeft naar deze pull request verwezen vanuit een commit %s` +pulls.commit_ref_at = `heeft naar deze pull request verwezen vanuit een commit %[2]s` pulls.cmd_instruction_hint = Bekijk opdrachtregelinstructies pulls.cmd_instruction_checkout_desc = Vanuit uw project repository, schakel over naar een nieuwe branch en test de veranderingen. pulls.showing_specified_commit_range = Alleen veranderingen weergeven tussen %[1]s..%[2]s @@ -2912,14 +2912,6 @@ comment.blocked_by_user = Commentaar geven is niet mogelijk omdat u geblokkeerd sync_fork.button = Synchroniseer sync_fork.branch_behind_one = Deze branch is %[1]d commit achter %[2]s sync_fork.branch_behind_few = Deze branch is %[1]d commits achter %[2]s -settings.event_action_failure = Mislukking -settings.event_action_failure_desc = Action run is mislukt. -settings.event_action_recover = Herstel -settings.event_action_success = Succes -settings.event_action_success_desc = Action run is geslaagd. -settings.event_header_action = Actie run evenementen -issues.filter_type.all_pull_requests = Alle pull requests -settings.event_action_recover_desc = Action run is geslaagd nadat de laatste action run in dezelfde workflow is mislukt. diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index 189e663618..86a333a886 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -1460,13 +1460,13 @@ issues.close_comment_issue=Zamknij z komentarzem issues.reopen_issue=Otwórz ponownie issues.reopen_comment_issue=Otwórz ponownie z komentarzem issues.create_comment=Skomentuj -issues.closed_at=`zamknął(-ęła) to zgłoszenie %s` -issues.reopened_at=`otworzył(-a) ponownie to zgłoszenie %s` -issues.commit_ref_at=`wspomniał(-a) to zgłoszenie z commita %s` -issues.ref_issue_from=`odwołał(-a) się do tego zgłoszenia %[3]s %[1]s` -issues.ref_pull_from=`odwołał(-a) się do tego Pull Requesta %[3]s %[1]s` -issues.ref_closing_from=`odwołał(-a) się do pull requesta %[3]s, który zamknie to zgłoszenie %[1]s` -issues.ref_reopening_from=`odwołał(-a) się z pull requesta %[3]s, który otworzy na nowo to zgłoszenie %[1]s` +issues.closed_at=`zamknął(-ęła) to zgłoszenie %[2]s` +issues.reopened_at=`otworzył(-a) ponownie to zgłoszenie %[2]s` +issues.commit_ref_at=`wspomniał(-a) to zgłoszenie z commita %[2]s` +issues.ref_issue_from=`odwołał(-a) się do tego zgłoszenia %[4]s %[2]s` +issues.ref_pull_from=`odwołał(-a) się do tego Pull Requesta %[4]s %[2]s` +issues.ref_closing_from=`odwołał(-a) się do pull requesta %[4]s, który zamknie to zgłoszenie %[2]s` +issues.ref_reopening_from=`odwołał(-a) się z pull requesta %[4]s, który otworzy na nowo to zgłoszenie %[2]s` issues.ref_closed_from=`zamknął(-ęła) to zgłoszenie %[4]s %[2]s` issues.ref_reopened_from=`ponownie otworzył(-a) to zgłoszenie %[4]s %[2]s` issues.ref_from=`z %[1]s` @@ -1679,8 +1679,8 @@ pulls.update_branch_rebase=Aktualizuj branch przez rebase pulls.update_branch_success=Aktualizacja gałęzi powiodła się pulls.update_not_allowed=Nie masz uprawnień do aktualizacji gałęzi pulls.outdated_with_base_branch=Ta gałąź jest przestarzała w stosunku do gałęzi bazowej -pulls.closed_at=`zamknął(-ęła) ten pull request %s` -pulls.reopened_at=`otworzył(-a) ponownie ten Pull Request %s` +pulls.closed_at=`zamknął(-ęła) ten pull request %[2]s` +pulls.reopened_at=`otworzył(-a) ponownie ten Pull Request %[2]s` @@ -2643,7 +2643,7 @@ pulls.closed = Pull request zamknięty pulls.blocked_by_outdated_branch = Ten pull request jest zablokowany ponieważ jest przedawniony. pulls.blocked_by_changed_protected_files_1 = Ten pull request jest zablokowany ponieważ wprowadza zmiany do chronionego pliku: pulls.push_rejected_no_message = Wypchnięcie nie powiodło się: Wypchnięcie zostało odrzucone, ale nie otrzymano zdalnej wiadomości. Sprawdź hooki Git dla tego repozytorium.= -pulls.commit_ref_at = `odniósł się do tego pull requesta z commita %s` +pulls.commit_ref_at = `odniósł się do tego pull requesta z commita %[2]s` pulls.cmd_instruction_checkout_desc = Ze swojego repozytorium projektu, utwórz nową gałąź i przetestuj zmiany. pulls.clear_merge_message_hint = Wyczyszczenie wiadomości scalenia usunie tylko treść wiadomości commitu pozostawiając wygenerowane przez git dopiski takie jak "Co-Authored-By ...". pulls.delete_after_merge.head_branch.insufficient_branch = Nie masz uprawnień by usunąć head gałęzi. diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index cd5cc14833..26bdd35420 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -1063,8 +1063,8 @@ language.localization_project = Ajude-nos a traduzir Forgejo para o seu idioma! language.description = Essa língua será salva em sua conta e será usada como padrão após você iniciar a sessão. user_block_yourself = Você não pode se bloquear. pronouns_custom_label = Pronomes personalizados -change_username_redirect_prompt.with_cooldown.one = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia. Você ainda pode recuperar o nome de usuário antigo durante este período de proteção. -change_username_redirect_prompt.with_cooldown.few = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dias. Você ainda pode recuperar o nome de usuário antigo durante este período de proteção. +change_username_redirect_prompt.with_cooldown.one = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dia, você ainda pode recuperar o nome de usuário antigo durante este período de espera. +change_username_redirect_prompt.with_cooldown.few = O nome de usuário antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dias, você ainda pode recuperar o nome de usuário antigo durante este período de espera. quota.applies_to_user = As seguintes regras de cota se aplicam à sua conta quota.rule.exceeded.helper = O tamanho total de objetos para esta regra excedeu a cota. keep_pronouns_private = Mostrar pronomes apenas para usuários autenticados @@ -1278,7 +1278,7 @@ star_guest_user=Entre para adicionar este repositório aos favoritos. unwatch=Deixar de observar watch=Observar unstar=Retirar dos favoritos -star=Adicionar aos favoritos +star=Juntar aos favoritos fork=Fork download_archive=Baixar repositório more_operations=Mais operações @@ -1568,7 +1568,7 @@ issues.remove_ref_at=`removeu a referência %s %s` issues.add_ref_at=`adicionou a referência %s %s` issues.delete_branch_at=`excluiu branch %s %s` issues.filter_label=Etiqueta -issues.filter_label_exclude=Use Alt + Clique para excluir etiquetas +issues.filter_label_exclude=`Use alt + clique/enter para excluir etiquetas` issues.filter_label_no_select=Todas as etiquetas issues.filter_label_select_no_label=Sem etiqueta issues.filter_milestone=Marco @@ -1642,13 +1642,13 @@ issues.close_comment_issue=Comentar e fechar issues.reopen_issue=Reabrir issues.reopen_comment_issue=Comentar e reabrir issues.create_comment=Comentar -issues.closed_at=`fechou esta issue %s` -issues.reopened_at=`reabriu esta issue %s` -issues.commit_ref_at=`citou esta issue de um commit %s` -issues.ref_issue_from=`citou esta issue %[3]s %[1]s` -issues.ref_pull_from=`citou este pull request %[3]s %[1]s` -issues.ref_closing_from=`citou esta issue de um pull request %[3]s que a fechará %[1]s` -issues.ref_reopening_from=`citou esta issue de um pull request %[3]s que a reabrirá, %[1]s` +issues.closed_at=`fechou esta issue %[2]s` +issues.reopened_at=`reabriu esta issue %[2]s` +issues.commit_ref_at=`citou esta issue em um commit %[2]s` +issues.ref_issue_from=`referenciado esta issue %[4]s %[2]s` +issues.ref_pull_from=`referenciado este pull request %[4]s %[2]s` +issues.ref_closing_from=`referenciado esta issue de um pull request %[4]s que a fechará %[2]s` +issues.ref_reopening_from=`referenciado esta issue de um pull request %[4]s que a reabrirá %[2]s` issues.ref_closed_from=`fechou esta issue %[4]s %[2]s` issues.ref_reopened_from=`reabriu esta issue %[4]s %[2]s` issues.ref_from=`de %[1]s` @@ -1934,7 +1934,7 @@ pulls.status_checks_success=Todas as verificações foram bem sucedidas pulls.status_checks_warning=Algumas verificações reportaram avisos pulls.status_checks_failure=Algumas verificações falharam pulls.status_checks_error=Algumas verificações reportaram erros -pulls.status_checks_requested=Obrigatório +pulls.status_checks_requested=Obrigatário pulls.status_checks_details=Detalhes pulls.update_branch=Atualizar branch por merge pulls.update_branch_rebase=Atualizar branch por rebase @@ -1942,8 +1942,8 @@ pulls.update_branch_success=Atualização do branch foi bem-sucedida pulls.update_not_allowed=Você não tem permissão para atualizar o branch pulls.outdated_with_base_branch=Este branch está desatualizado com o branch base pulls.close=Fechar pull request -pulls.closed_at=`fechou este pull request %s` -pulls.reopened_at=`reabriu este pull request %s` +pulls.closed_at=`fechou este pull request %[2]s` +pulls.reopened_at=`reabriu este pull request %[2]s` pulls.clear_merge_message=Limpar mensagem do merge pulls.clear_merge_message_hint=Limpar a mensagem de merge só irá remover o conteúdo da mensagem de commit e manter trailers git gerados, como "Co-Authored-By …". @@ -2719,7 +2719,7 @@ issues.label_archive_tooltip = Etiquetas arquivadas não serão exibidas nas sug activity.navbar.pulse = Recente settings.units.overview = Geral settings.units.add_more = Habilitar mais -pulls.commit_ref_at = `citou este pull request de um commit %s` +pulls.commit_ref_at = `referenciou este pedido de mesclagem no commit %[2]s` pulls.cmd_instruction_merge_title = Mesclar settings.units.units = Unidades vendored = Externo @@ -2803,7 +2803,7 @@ mirror_use_ssh.helper = Forgejo irá espelhar o repositório via Git através de mirror_denied_combination = Não é possível combinar o uso de chave pública e autenticação baseada em senha. mirror_public_key = Chave SSH pública mirror_use_ssh.text = Usar autenticação por SSH -mirror_use_ssh.not_available = A autenticação via SSH não está disponível. +mirror_use_ssh.not_available = Autenticação por SSH não está disponível. settings.push_mirror_sync_in_progress = Fazendo push das mudanças para o remoto %s nesse momento. settings.federation_apapiurl = URL de federação deste repositório. Copie e cole isso nas Configurações de Federação de outro repositório como uma URL de um Repositório Seguidor. pulls.agit_explanation = Criado usando o fluxo de trabalho AGit. AGit permite que contribuidores proponham mudanças usando "git push" sem criar um fork ou novo branch. @@ -2817,7 +2817,7 @@ settings.mirror_settings.pushed_repository = Repositório enviado settings.mirror_settings.docs.disabled_pull_mirror.instructions = Configure seu projeto para automaticamente fazer push de commits, tags e branches para outro repositório. Espelhos de pull foram desativados pelo administrador do seu site. settings.mirror_settings.docs.disabled_push_mirror.instructions = Configure seu projeto para automaticamente fazer pull de commits, tags e branches de outro repositório. settings.mirror_settings.docs.doc_link_pull_section = a seção "Fazendo pull de um repositório remoto" da documentação. -subscribe.pull.guest.tooltip = Inicie a sessão para receber notificações deste pull request. +subscribe.pull.guest.tooltip = Entre para receber notificações deste pull request. settings.pull_mirror_sync_quota_exceeded = Cota excedida, não será feito pull das mudanças. settings.mirror_settings.docs.more_information_if_disabled = Saiba mais sobre espelhos de push e pull aqui: settings.transfer_quota_exceeded = O novo dono (%s) excedeu a cota. O repositório não foi transferido. @@ -2920,7 +2920,6 @@ settings.event_action_recover = Recuperar settings.event_action_recover_desc = A execução da Action teve sucesso após a última execução no mesmo workflow ter falhado. settings.event_action_success = Sucesso settings.event_action_success_desc = A execução da Action foi bem sucedida. -issues.filter_type.all_pull_requests = Todos os pull requests [graphs] component_loading = Carregando %s… @@ -3057,8 +3056,8 @@ open_dashboard = Abrir painel settings.change_orgname_prompt = Obs.: Alterar o nome de uma organização resultará na alteração do URL dela e disponibilizará o nome antigo para uso. follow_blocked_user = Não foi possível seguir esta organização porque ela bloqueou-o(a). form.name_pattern_not_allowed = O padrão "%s" não é permitido no nome de uma organização. -settings.change_orgname_redirect_prompt.with_cooldown.one = O nome de organização antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia. Você ainda pode recuperar o nome antigo durante este período de proteção. -settings.change_orgname_redirect_prompt.with_cooldown.few = O nome de organização antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia. Você ainda pode recuperar o nome antigo durante este período de proteção. +settings.change_orgname_redirect_prompt.with_cooldown.one = O nome de organização antigo ficará disponível para qualquer pessoa após um período de proteção de %[1]d dia, você ainda pode recuperar o nome antigo durante este período de proteção. +settings.change_orgname_redirect_prompt.with_cooldown.few = O nome de organização antigo ficará disponível para qualquer pessoa após um período de espera de %[1]d dia, você ainda pode recuperar o nome antigo durante este período de espera. [admin] dashboard=Painel @@ -3900,7 +3899,7 @@ deletion=Excluir segredo deletion.description=A exclusão de um segredo é permanente e não pode ser desfeita. Continuar? deletion.success=O segredo foi excluído. deletion.failed=Falha ao excluir segredo. -management=Gerenciamento de segredos +management=Gerenciar segredos [actions] actions=Ações @@ -3909,12 +3908,12 @@ unit.desc=Gerenciar pipelines integradas de CI/CD com Forgejo Actions. status.unknown=Desconhecido status.waiting=Aguardando -status.running=Executando +status.running=Rodando status.success=Sucesso status.failure=Falha -status.cancelled=Cancelada -status.skipped=Ignorada -status.blocked=Bloqueada +status.cancelled=Cancelado +status.skipped=Ignorado +status.blocked=Bloqueado runners=Runners runners.runner_manage_panel=Gerenciar runners diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 9e1c7f7f63..7f36d164b3 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -1063,8 +1063,8 @@ language.description = Este idioma vai ser guardado na sua conta e ser usado com language.localization_project = Ajude-nos a traduzir o Forgejo para o seu idioma! Ler mais. pronouns_custom_label = Pronomes personalizados user_block_yourself = Não se pode bloquear a si próprio. -change_username_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia. Pode ainda reivindicar o nome de utilizador antigo durante o período de espera. -change_username_redirect_prompt.with_cooldown.few = O nome de utilizador antigo ficará disponível para todos após um período de espera de %[1]d dias. Pode ainda reivindicar o nome de utilizador antigo durante o período de espera. +change_username_redirect_prompt.with_cooldown.one = O nome de utilizador antigo estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera. +change_username_redirect_prompt.with_cooldown.few = O nome de utilizador antigo ficará disponível para todos após um período de espera de %[1]d dias, podendo ainda reivindicar o nome de utilizador antigo durante o período de espera. quota.applies_to_user = As seguintes regras de quotas aplicam-se à sua conta quota.sizes.assets.artifacts = Artefactos quota.rule.exceeded.helper = O tamanho total dos objectos para esta regra excedeu a quota. @@ -1583,7 +1583,7 @@ issues.remove_ref_at=`removeu a referência %s %s` issues.add_ref_at=`adicionou a referência %s %s` issues.delete_branch_at=`eliminou o ramo %s %s` issues.filter_label=Rótulo -issues.filter_label_exclude=Use Alt + Clique para excluir rótulos +issues.filter_label_exclude=`Use alt + clique/enter para excluir rótulos` issues.filter_label_no_select=Todos os rótulos issues.filter_label_select_no_label=Sem rótulo issues.filter_milestone=Etapa @@ -1657,13 +1657,13 @@ issues.close_comment_issue=Fechar com comentário issues.reopen_issue=Reabrir issues.reopen_comment_issue=Reabrir com comentário issues.create_comment=Comentar -issues.closed_at=`encerrou esta questão %s` -issues.reopened_at=`reabriu esta questão %s` -issues.commit_ref_at=`referenciou esta questão num cometimento %s` -issues.ref_issue_from=`referiu esta questão %[3]s %[1]s` -issues.ref_pull_from=`referiu este pedido de integração %[3]s %[1]s` -issues.ref_closing_from=`referiu esta questão a partir de um pedido de integração %[3]s que a fechará %[1]s` -issues.ref_reopening_from=`referiu esta questão a partir de um pedido de integração %[3]s que a reabrirá %[1]s` +issues.closed_at=`encerrou esta questão %[2]s` +issues.reopened_at=`reabriu esta questão %[2]s` +issues.commit_ref_at=`referenciou esta questão num cometimento %[2]s` +issues.ref_issue_from=`referiu esta questão %[4]s %[2]s` +issues.ref_pull_from=`referiu este pedido de integração %[4]s %[2]s` +issues.ref_closing_from=`referiu esta questão a partir de um pedido de integração %[4]s que a fechará %[2]s` +issues.ref_reopening_from=`referiu esta questão a partir de um pedido de integração %[4]s que a reabrirá %[2]s` issues.ref_closed_from=`encerrou esta questão %[4]s %[2]s` issues.ref_reopened_from=`reabriu esta questão %[4]s %[2]s` issues.ref_from=`de %[1]s` @@ -1972,8 +1972,8 @@ pulls.update_branch_success=A sincronização do ramo foi bem sucedida pulls.update_not_allowed=Não tem autorização para sincronizar o ramo pulls.outdated_with_base_branch=Este ramo é obsoleto em relação ao ramo base pulls.close=Encerrar pedido de integração -pulls.closed_at=`fechou este pedido de integração %s` -pulls.reopened_at=`reabriu este pedido de integração %s` +pulls.closed_at=`fechou este pedido de integração %[2]s` +pulls.reopened_at=`reabriu este pedido de integração %[2]s` pulls.cmd_instruction_hint=Ver instruções para a linha de comandos pulls.cmd_instruction_checkout_title=Conferir pulls.cmd_instruction_checkout_desc=No seu repositório, irá criar um novo ramo para que possa testar as modificações. @@ -2785,7 +2785,7 @@ settings.wiki_rename_branch_main_desc = Renomear o ramo usado internamente pelo settings.add_collaborator_blocked_our = Não foi possível adicionar o/a colaborador/a porque o/a proprietário/a do repositório bloqueou-os. settings.add_webhook.invalid_path = A localização não pode conter "." ou ".." ou ficar em branco. Não pode começar ou terminar com uma barra. settings.graphql_url = URL do GraphQL -pulls.commit_ref_at = `referiu este pedido de integração a partir de um cometimento %s` +pulls.commit_ref_at = `referiu este pedido de integração a partir de um cometimento %[2]s` settings.confirm_wiki_branch_rename = Renomear o ramo do wiki settings.wiki_branch_rename_success = O nome do ramo do wiki do repositório foi normalizado com sucesso. settings.wiki_branch_rename_failure = Falhou a normalização do nome do ramo do wiki do repositório. @@ -2922,7 +2922,6 @@ settings.event_header_action = Eventos da execução de ações settings.event_action_recover_desc = A execução de ação foi bem sucedida depois da última execução de ação na mesma sequência de trabalho ter falhado. settings.event_action_success = Sucesso settings.event_action_success_desc = A Execução de ação foi bem sucedida. -issues.filter_type.all_pull_requests = Todos os pedidos de integração [graphs] component_loading=A carregar %s… @@ -3058,8 +3057,8 @@ teams.invite.by=Convidado(a) por %s teams.invite.description=Clique no botão abaixo para se juntar à equipa. follow_blocked_user = Não pode seguir esta organização porque esta organização bloqueou-o/a. open_dashboard = Abrir painel de controlo -settings.change_orgname_redirect_prompt.with_cooldown.one = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dia. Pode ainda reivindicar o nome antigo durante o período de espera. -settings.change_orgname_redirect_prompt.with_cooldown.few = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dias. Pode ainda reivindicar o nome antigo durante o período de espera. +settings.change_orgname_redirect_prompt.with_cooldown.one = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dia, podendo ainda reivindicar o nome antigo durante o período de espera. +settings.change_orgname_redirect_prompt.with_cooldown.few = O nome antigo da organização estará disponível para todos após um período de espera de %[1]d dias, podendo ainda reivindicar o nome antigo durante o período de espera. [admin] dashboard=Painel de controlo diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 2ef1b868d4..9158329978 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -1563,7 +1563,7 @@ issues.remove_ref_at=`убрана ссылка на %s %s` issues.add_ref_at=`добавлена ссылка на %s %s` issues.delete_branch_at=`удалена ветвь %s %s` issues.filter_label=Метки -issues.filter_label_exclude=Исключайте метки с помощью Alt + ЛКМ +issues.filter_label_exclude=`Исключайте метки с помощью alt + лкм/enter` issues.filter_label_no_select=Любые метки issues.filter_label_select_no_label=Без меток issues.filter_milestone=Этап @@ -1637,13 +1637,13 @@ issues.close_comment_issue=Закрыть комментарием issues.reopen_issue=Открыть снова issues.reopen_comment_issue=Открыть снова комментарием issues.create_comment=Комментировать -issues.closed_at=`задача была закрыта %s` -issues.reopened_at=`задача была открыта снова %s` -issues.commit_ref_at=`упоминание этой задачи в коммите %s` -issues.ref_issue_from=`упоминание этой задачи %[3]s %[1]s` -issues.ref_pull_from=`упоминание этого запроса слияния %[3]s %[1]s` -issues.ref_closing_from=`упоминание из запроса на слияние %[3]s, который закроет эту задачу %[1]s` -issues.ref_reopening_from=`упоминание из запроса на слияние %[3]s, который повторно откроет эту задачу %[1]s` +issues.closed_at=`задача была закрыта %[2]s` +issues.reopened_at=`задача была открыта снова %[2]s` +issues.commit_ref_at=`упоминание этой задачи в коммите %[2]s` +issues.ref_issue_from=`упоминание этой задачи %[4]s %[2]s` +issues.ref_pull_from=`упоминание этого запроса слияния %[4]s %[2]s` +issues.ref_closing_from=`упоминание из запроса на слияние %[4]s, который закроет эту задачу %[2]s` +issues.ref_reopening_from=`упоминание из запроса на слияние %[4]s, который повторно откроет эту задачу %[2]s` issues.ref_closed_from=`закрыл этот запрос %[4]s %[2]s` issues.ref_reopened_from=`задача была открыта снова %[4]s %[2]s` issues.ref_from=`из %[1]s` @@ -1943,8 +1943,8 @@ pulls.update_branch_success=Ветвь успешно обновлена pulls.update_not_allowed=Недостаточно прав для обновления ветви pulls.outdated_with_base_branch=Эта ветвь отстает от базовой ветви pulls.close=Закрыть запрос слияния -pulls.closed_at=`закрыл этот запрос на слияние %s` -pulls.reopened_at=`переоткрыл этот запрос на слияние %s` +pulls.closed_at=`закрыл этот запрос на слияние %[2]s` +pulls.reopened_at=`переоткрыл этот запрос на слияние %[2]s` pulls.cmd_instruction_hint=Показать инструкции для командной строки pulls.cmd_instruction_merge_title=Слейте изменения pulls.cmd_instruction_merge_desc=Слейте изменения и отправьте их обратно. @@ -2772,7 +2772,7 @@ settings.ignore_stale_approvals = Игнорировать устаревшие contributors.contribution_type.additions = Добавления contributors.contribution_type.deletions = Удаления contributors.contribution_type.filter_label = Вид деятельности: -pulls.commit_ref_at = `сослался на этот запрос слияния в коммите %s` +pulls.commit_ref_at = `упоминание этого запроса слияния в коммите %[2]s` settings.thread_id = ИД обсуждения pulls.made_using_agit = AGit activity.navbar.contributors = Соавторы diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini index 54b0b246db..d55b238b1c 100644 --- a/options/locale/locale_si-LK.ini +++ b/options/locale/locale_si-LK.ini @@ -1100,12 +1100,12 @@ issues.close_comment_issue=අදහස් දක්වා වසන්න issues.reopen_issue=නැවත විවෘත කරන්න issues.reopen_comment_issue=අදහස් දක්වා විවෘත කරන්න issues.create_comment=අදහස -issues.closed_at=`මෙම ගැටළුව වසා %s` -issues.reopened_at=`මෙම ගැටළුව නැවත විවෘත කරන ලදි %s` -issues.ref_issue_from=`මෙම නිකුතුව %[3]s හි %[1]s` -issues.ref_pull_from=`මෙම අදින්න ඉල්ලීම%[3]s %[1]s` -issues.ref_closing_from=`මෙම ගැටළුව වසා දමනු ඇත%[3]s මෙම ගැටළුව %[1]s` -issues.ref_reopening_from=`මෙම ගැටළුව නැවත විවෘත කරනු ඇත%[3]s මෙම ගැටළුව %[1]s` +issues.closed_at=`මෙම ගැටළුව වසා %[2]s` +issues.reopened_at=`මෙම ගැටළුව නැවත විවෘත කරන ලදි %[2]s` +issues.ref_issue_from=`මෙම නිකුතුව %[4]s හි %[2]s` +issues.ref_pull_from=`මෙම අදින්න ඉල්ලීම%[4]s %[2]s` +issues.ref_closing_from=`මෙම ගැටළුව වසා දමනු ඇත%[4]s මෙම ගැටළුව %[2]s` +issues.ref_reopening_from=`මෙම ගැටළුව නැවත විවෘත කරනු ඇත%[4]s මෙම ගැටළුව %[2]s` issues.ref_closed_from=`මෙම නිකුතුව%[4]s %[2]s` issues.ref_reopened_from=`මෙම නිකුතුව%[4]s %[2]sනැවත විවෘත කරන ලදි` issues.ref_from=`හිම%[1]s` @@ -1342,8 +1342,8 @@ pulls.update_branch_rebase=රිබේස් මගින් ශාඛාව pulls.update_branch_success=ශාඛා යාවත්කාලීන කිරීම සාර්ථක විය pulls.update_not_allowed=ශාඛාව යාවත්කාලීන කිරීමට ඔබට අවසර නැත pulls.outdated_with_base_branch=මෙම ශාඛාව මූලික ශාඛාව සමඟ දිවයයි -pulls.closed_at=`මෙම අදින්න ඉල්ලීම වසා %s` -pulls.reopened_at=`මෙම අදින්න ඉල්ලීම නැවත විවෘත කරන ලදි %s` +pulls.closed_at=`මෙම අදින්න ඉල්ලීම වසා %[2]s` +pulls.reopened_at=`මෙම අදින්න ඉල්ලීම නැවත විවෘත කරන ලදි %[2]s` diff --git a/options/locale/locale_sr-SP.ini b/options/locale/locale_sr-SP.ini index b14fdc1a35..56c1a7e650 100644 --- a/options/locale/locale_sr-SP.ini +++ b/options/locale/locale_sr-SP.ini @@ -326,7 +326,7 @@ issues.no_content=Још нема садржаја. issues.close_issue=Затвори issues.reopen_issue=Поново отвори issues.create_comment=Коментирај -issues.commit_ref_at=`поменуо овај задатак у комит %s` +issues.commit_ref_at=`поменуо овај задатак у комит %[2]s` issues.poster=Аутор issues.collaborator=Коаутор issues.owner=Власник diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index 2e212c8c49..541acbf408 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -918,7 +918,7 @@ migrate.migrate_items_options=Åtkomsttoken krävs för att migrera ytterligare migrated_from=Migrerad från %[2]s migrated_from_fake=Migrerad från %[1]s migrate.migrate=Migrera från %s -migrate.migrating=Migrerar från %s … +migrate.migrating=Migrerar från %s ... migrate.migrating_failed=Migrering från %s misslyckades. migrate.migrating_issues=Migrerar ärenden @@ -1157,13 +1157,13 @@ issues.close_comment_issue=Stäng med kommentar issues.reopen_issue=Återöppna issues.reopen_comment_issue=Öppna igen med kommentar issues.create_comment=Kommentera -issues.closed_at=`stängde ärendet %s` -issues.reopened_at=`återöppnade detta ärende %s` -issues.commit_ref_at=`refererade till detta ärende från en incheckning %s` -issues.ref_issue_from=`refererade till detta ärende %[3]s %[1]s` -issues.ref_pull_from=`refererade till denna pull-förfrågan %[3]s %[1]s` -issues.ref_closing_from=`hänvisade till detta ärende från en pull-förfrågan %[3]s som kommer att stänga det %[1]s` -issues.ref_reopening_from=`hänvisade till detta ärende från en pull-förfrågan %[3]s som kommer att öppna ärendet på nytt %[1]s` +issues.closed_at=`stängde ärendet %[2]s` +issues.reopened_at=`återöppnade detta ärende %[2]s` +issues.commit_ref_at=`refererade till detta ärende från en incheckning %[2]s` +issues.ref_issue_from=`refererade till detta ärende %[4]s %[2]s` +issues.ref_pull_from=`refererade till denna pull-förfrågan %[4]s %[2]s` +issues.ref_closing_from=`hänvisade till detta ärende från en pull-förfrågan %[4]s som kommer att stänga det %[2]s` +issues.ref_reopening_from=`hänvisade till detta ärende från en pull-förfrågan %[4]s som kommer att öppna ärendet på nytt %[2]s` issues.ref_closed_from=`stängde detta ärende %[4]s %[2]s` issues.ref_reopened_from=`öpnnade detta ärende igen %[4]s %[2]s` issues.ref_from=`från %[1]s` @@ -2324,15 +2324,15 @@ exact = Exakt exact_tooltip = Inkludera bara resultat som exakt matchar söktermen repo_kind = Sök repon… user_kind = Sök användare… -code_kind = Sök kod… -package_kind = Sök paket… +code_kind = Sök kod... +package_kind = Sök paket... runner_kind = Sök exekutorer... -branch_kind = Sök grenar… +branch_kind = Sök grenar... commit_kind = Sök commiter... -project_kind = Sök projekt… +project_kind = Sök projekt... search = Sök… type_tooltip = Söktyp -team_kind = Sök team… +team_kind = Sök lag... org_kind = Sök organisationer… issue_kind = Sök ärenden... regexp_tooltip = Tolka söktermen som ett reguljärt uttryck diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index c07cefdab9..4f51ddcc7e 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -1594,13 +1594,13 @@ issues.close_comment_issue=Yorum Yap ve Kapat issues.reopen_issue=Yeniden aç issues.reopen_comment_issue=Yorum Yap ve Yeniden Aç issues.create_comment=Yorum yap -issues.closed_at=`%s konusunu kapattı` -issues.reopened_at=`%s konusunu yeniden açtı` -issues.commit_ref_at=`%s işlemesinde bu konuyu işaret etti` -issues.ref_issue_from=`bu konuya referansta bulundu %[3]s %[1]s` -issues.ref_pull_from=`bu değişiklik isteğine referansta bulundu %[3]s %[1]s` -issues.ref_closing_from=`bir değişiklik isteğine referansta bulundu %[3]s bu konu kapatılacak %[1]s` -issues.ref_reopening_from=`bir değişiklik isteğine referansta bulundu %[3]s bu konu yeniden açılacak %[1]s` +issues.closed_at=`%[2]s konusunu kapattı` +issues.reopened_at=`%[2]s konusunu yeniden açtı` +issues.commit_ref_at=`%[2]s işlemesinde bu konuyu işaret etti` +issues.ref_issue_from=`bu konuya referansta bulundu %[4]s %[2]s` +issues.ref_pull_from=`bu değişiklik isteğine referansta bulundu %[4]s %[2]s` +issues.ref_closing_from=`bir değişiklik isteğine referansta bulundu %[4]s bu konu kapatılacak %[2]s` +issues.ref_reopening_from=`bir değişiklik isteğine referansta bulundu %[4]s bu konu yeniden açılacak %[2]s` issues.ref_closed_from=`bu konuyu kapat%[4]s %[2]s` issues.ref_reopened_from=`konuyu yeniden aç%[4]s %[2]s` issues.ref_from=`%[1]s'den` @@ -1907,8 +1907,8 @@ pulls.update_branch_success=Dal güncellemesi başarıyla gerçekleştirildi pulls.update_not_allowed=Dalı güncelleme izniniz yok pulls.outdated_with_base_branch=Bu dal, temel dal ile güncel değil pulls.close=Değişiklik İsteğini Kapat -pulls.closed_at=`%s değişiklik isteğini kapattı` -pulls.reopened_at=`%s değişiklik isteğini yeniden açtı` +pulls.closed_at=`%[2]s değişiklik isteğini kapattı` +pulls.reopened_at=`%[2]s değişiklik isteğini yeniden açtı` pulls.cmd_instruction_hint=`Komut satırı talimatlarını görüntüleyin.` pulls.cmd_instruction_checkout_title=Çekme pulls.cmd_instruction_checkout_desc=Proje deponuzdan yeni bir dalı çekin ve değişiklikleri test edin. diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index 331c7403eb..2e536c3d1a 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -198,7 +198,7 @@ buttons.disable_monospace_font = Вимкнути моноширинний шр buttons.indent.tooltip = Вкласти предмет на один рівень buttons.unindent.tooltip = Викласти об'єкт на один рівень buttons.mention.tooltip = Згадати користувача чи команду -buttons.ref.tooltip = Послатися на задачу чи на запит на злиття +buttons.ref.tooltip = Послатись на задачу чи на запит на злиття buttons.enable_monospace_font = Увімкнути моноширинний шрифт buttons.new_table.tooltip = Додати таблицю table_modal.label.columns = Стовпці @@ -694,7 +694,7 @@ disabled_public_activity=Цей користувач вимкнув публіч joined_on = Реєстрація %s email_visibility.private = Ваш email видно лише вам і адміністраторам email_visibility.limited = Вашу е-пошту видно всім авторизованим -settings = Користувацькі налаштування +settings = Користувацькі параметри block_user.detail_3 = Ви не зможете додати один одного в якості співавтора репозиторію. show_on_map = Показати це місце на мапі block_user.detail_2 = Цей користувач не зможе взаємодіяти з репозиторіями, власником яких є ви, а також із задачами та коментарями, які ви створили. @@ -1276,7 +1276,7 @@ file_raw=Неформатований file_history=Історія file_view_source=Переглянути вихідний код file_view_rendered=Переглянути відрендерено -file_view_raw=Переглянути неформатований +file_view_raw=Перегляд Raw file_permalink=Постійне посилання file_too_large=Цей файл завеликий щоб бути показаним. @@ -1447,7 +1447,7 @@ issues.remove_ref_at=`видалив посилання %s %s` issues.add_ref_at=`додав посилання %s %s` issues.delete_branch_at=`видалена гілка %s %s` issues.filter_label=Мітка -issues.filter_label_exclude=Використовуйте Alt + клік для виключення міток +issues.filter_label_exclude=`Використовуйте Alt + клік/Enter для виключення міток` issues.filter_label_no_select=Всі мітки issues.filter_milestone=Етап issues.filter_project=Проєкт @@ -1496,17 +1496,17 @@ issues.context.quote_reply=Цитувати відповідь issues.context.reference_issue=Послатися в новій задачі issues.context.edit=Редагувати issues.context.delete=Видалити -issues.close_comment_issue=Закрити з коментарем +issues.close_comment_issue=Прокоментувати і закрити issues.reopen_issue=Відкрити знову -issues.reopen_comment_issue=Відкрити знову з коментарем +issues.reopen_comment_issue=Прокоментувати та відкрити знову issues.create_comment=Коментар -issues.closed_at=`закриває цю задачу %s` -issues.reopened_at=`повторно відкриває цю задачу %s` -issues.commit_ref_at=`посилається на цю задачу в коміті %s` -issues.ref_issue_from=`посилається на цю задачу %[3]s %[1]s` -issues.ref_pull_from=`посилається на цей запит злиття %[3]s %[1]s` -issues.ref_closing_from=`посилається в запиті на злиття %[3]s, який закриє цю задачу, %[1]s` -issues.ref_reopening_from=`посилається в запиті на злиття %[3]s, який повторно відкриє цю задачу, %[1]s` +issues.closed_at=`закрив цю задачу %[2]s` +issues.reopened_at=`повторно відкрив цю задачу %[2]s` +issues.commit_ref_at=`згадано цю задачу в коміті %[2]s` +issues.ref_issue_from=`посилається на цю задачу %[4]s %[2]s` +issues.ref_pull_from=`послався на цей запит злиття %[4]s %[2]s` +issues.ref_closing_from=`згадав запит на злиття %[4]s, які закриють цю задачу %[2]s` +issues.ref_reopening_from=`згадав запит на злиття %[4]s, які повторно відкриють цю задачу %[2]s` issues.ref_closed_from=`закрив цю задачу %[4]s %[2]s` issues.ref_reopened_from=`повторно відкрито цю задачу %[4]s %[2]s` issues.ref_from=`із %[1]s` @@ -1743,8 +1743,8 @@ pulls.update_branch_rebase=Оновити гілку перебазування pulls.update_branch_success=Оновлення гілки пройшло успішно pulls.update_not_allowed=Ви не можете оновити гілку pulls.outdated_with_base_branch=Ця гілка застаріла відносно базової гілки -pulls.closed_at=`закриває цей запит на злиття %s` -pulls.reopened_at=`повторно відкриває цей запит на злиття %s` +pulls.closed_at=`закрив цей запит на злиття %[2]s` +pulls.reopened_at=`повторно відкрив цей запит на злиття %[2]s` @@ -1887,7 +1887,7 @@ settings.collaboration.owner=Власник settings.collaboration.undefined=Не визначено settings.hooks=Веб-хуки settings.githooks=Git хуки -settings.basic_settings=Основні налаштування +settings.basic_settings=Базові налаштування settings.mirror_settings=Налаштування дзеркала settings.mirror_settings.mirrored_repository=Віддзеркалений репозиторій settings.mirror_settings.direction=Напрямок @@ -2055,12 +2055,12 @@ settings.event_issue_assign=Призначення settings.event_issue_assign_desc=Задачу призначено або скасовано. settings.event_issue_label=Мітки settings.event_issue_label_desc=Додавання або видалення міток задач. -settings.event_issue_milestone=Етапи +settings.event_issue_milestone=Задача з етапом settings.event_issue_milestone_desc=Етап призначено, видалено або змінено. settings.event_issue_comment=Коментарі settings.event_issue_comment_desc=Коментар задачі створено, видалено чи відредаговано. settings.event_header_pull_request=Події запиту на злиття -settings.event_pull_request=Зміна +settings.event_pull_request=Запити до злиття settings.event_pull_request_desc=Запит до злиття відкрито, закрито, перевідкрито або відредаговано. settings.event_pull_request_assign=Призначення settings.event_pull_request_assign_desc=Запит про злиття призначено або скасовано. @@ -2485,7 +2485,7 @@ signing.will_sign = Коміт буде підписано ключем «%s». signing.wont_sign.error = Під час перевірки можливості підписати коміт сталася помилка. commits.search_branch = У цій гілці ext_wiki = Зовнішня вікі -pulls.commit_ref_at = `посилається на цей запит на злиття в коміті %s` +pulls.commit_ref_at = `посилається на цей запит на злиття в коміті %[2]s` pulls.cmd_instruction_hint = Переглянути інструкції для командного рядка issues.max_pinned = Неможливо закріпити більше задач issues.unpin_comment = відкріпив %s @@ -2669,31 +2669,6 @@ settings.event_action_recover = Відновлено commitstatus.success = Успіх commitstatus.failure = Збій issues.filter_type.all_pull_requests = Усі запити на злиття -broken_message = Неможливо прочитати дані Git, що лежать в основі цього репозиторію. Зверніться до адміністратора цього екземпляра або видаліть репозиторій. -migrate.invalid_local_path = Локальний шлях недійсний. Він не існує або не є каталогом. -editor.filename_is_a_directory = Назва файлу «%s» уже використовується в цьому репозиторії як назва каталогу. -editor.filename_is_invalid = Хибна назва файлу: «%s». -migrate_options_lfs_endpoint.placeholder = Якщо залишити порожнім, то кінцеву точку буде визначено з URL-адреси клону -cite_this_repo = Послатися на цей репозиторій -editor.directory_is_a_file = Назва каталогу «%s» уже використовується в цьому репозиторії як назва файлу. -subscribe.issue.guest.tooltip = Увійдіть, щоб підписатися на цю задачу. -invisible_runes_header = `Цей файл містить невидимі символи Юнікоду` -invisible_runes_line = `У цьому рядку є невидимі символи Юнікоду` -subscribe.pull.guest.tooltip = Увійдіть, щоб підписатися на цей запит на злиття. -ambiguous_runes_header = `Цей файл містить неоднозначні символи Юнікоду` -ambiguous_runes_line = `У цьому рядку є неоднозначні символи Юнікоду` -issues.choose.invalid_config = У конфігурації задачі є помилки: -escape_control_characters = Escape -ambiguous_runes_description = `Цей файл містить символи Юнікоду, які легко сплутати з іншими символами. Якщо так зроблено навмисно, можете ігнорувати це попередження. Щоб показати ці символи, скористайтеся кнопкою «Escape».` -unescape_control_characters = Unescape -invisible_runes_description = `Цей файл містить невидимі символи Юнікоду, які людині неможливо розрізнити, але які по-різному обробляються комп'ютером. Якщо так зроблено навмисно, можете ігнорувати це попередження. Щоб показати ці символи, скористайтеся кнопкою «Escape».` -ambiguous_character = `%[1]c [U+%04[1]X] можна сплутати з %[2]c [U+%04[2]X]` -settings.sourcehut_builds.secrets_helper = Надати завданню доступ до секретів збірки (потрібен дозвіл SECRETS:RO) -no_eol.text = Без EOL -settings.remove_protected_branch_failed = Не вдалося видалити правило захисту гілок «%s». -summary_card_alt = Підсумкова картка репозиторію %s -issues.summary_card_alt = Підсумкова картка задачі «%s» в репозиторії %s -release.summary_card_alt = Підсумкова картка випуску «%s» в репозиторії %s [graphs] contributors.what = внески @@ -2872,7 +2847,7 @@ dashboard.update_migration_poster_id=Оновити мігровані ID авт dashboard.git_gc_repos=Виконати очистку сміття для всіх репозиторіїв dashboard.resync_all_sshkeys=Оновити файл «.ssh/authorized_keys» з SSH-ключами Forgejo. dashboard.resync_all_sshprincipals=Оновити файл «.ssh/authorized_principals» з SSH даними користувача Forgejo. -dashboard.resync_all_hooks=Пересинхронізувати хуки pre-receive, update та post-receive в усіх репозиторіях +dashboard.resync_all_hooks=Пересинхронізувати перед-прийнятні, оновлюючі та пост-прийнятні хуки в усіх репозиторіях dashboard.reinit_missing_repos=Переініціалізувати усі репозитрії git-файли яких втрачено dashboard.sync_external_users=Синхронізувати дані зовнішніх користувачів dashboard.cleanup_hook_task_table=Очистити hook_task таблицю @@ -2931,7 +2906,7 @@ users.edit_account=Редагувати обліковий запис users.max_repo_creation=Максимальна кількість репозиторіїв users.max_repo_creation_desc=(Введіть -1, щоб використовувати глобальний ліміт за замовчуванням.) users.is_activated=Обліковий запис користувача увімкнено -users.prohibit_login=Заблокований обліковий запис +users.prohibit_login=Вимкнути вхід users.is_admin=Обліковий запис адміністратора users.is_restricted=Обмежений users.allow_git_hook=Може створювати Git хуки @@ -3218,7 +3193,7 @@ config.git_gc_timeout=Тайм-аут операції збирача смітт config.log_config=Конфігурація журналу config.disabled_logger=Вимкнено -config.access_log_mode=Режим журналювання доступу +config.access_log_mode=Режим доступу до журналу config.xorm_log_sql=Журнал SQL @@ -3275,7 +3250,7 @@ packages.package_manage_panel = Керування пакунками packages.published = Опубліковано notices.operations = Дії packages.cleanup = Очистити недійсні дані -packages.cleanup.success = Недійсні дані успішно очищено +packages.cleanup.success = Успішно очищено недійсні дані users.still_own_packages = Цей користувач досі володіє одним чи більше пакунками, спочатку видаліть ці пакунки. users.purge_help = Примусово видалити користувача і будь-які репозиторії, організації та пакунки, якими він володіє. Всі коментарі та задачі, створені цим користувачем, також будуть видалені. dashboard.cleanup_packages = Очистити непридатні пакунки @@ -3330,13 +3305,6 @@ dashboard.cron.cancelled = Cron: %[1]s скасовано: %[3]s defaulthooks.desc = Вебхуки автоматично сповіщають HTTP-сервер POST-запитами, коли в Forgejo відбуваються певні події. Вказані тут вебхуки є типовими і будуть скопійовані до всіх нових репозиторіїв. Докладніше — в посібнику з вебхуків. assets = Ресурси коду auths.invalid_openIdConnectAutoDiscoveryURL = Неправильна URL-адреса автоматичного виявлення (повинна бути дійсна URL-адреса, що починається з http:// або https://) -settings = Налаштування адміністратора -dashboard.start_schedule_tasks = Запустити заплановані завдання дій -config.logger_name_fmt = Журнал: %s -config.set_setting_failed = Не вдалося встановити параметр %s -config.access_log_template = Шаблон журналу доступу -dashboard.cancel_abandoned_jobs = Скасувати покинуті завдання дій -monitor.download_diagnosis_report = Завантажити діагностичний звіт [action] @@ -3557,8 +3525,6 @@ cran.registry = Налаштуйте цей реєстр у файлі Rpr npm.registry = Налаштуйте цей реєстр у файлі .npmrc свого проєкту: chef.registry = Налаштуйте цей реєстр у файлі ~/.chef/config.rb: owner.settings.chef.keypair.description = Запити до реєстру Chef повинні бути криптографічно підписані як засіб автентифікації. При генерації пари ключів на Forgejo зберігається тільки публічний ключ. Приватний ключ надається вам для використання команд knife. Генерація нової пари ключів замінить попередню. -nuget.dependency.framework = Цільовий фреймворк -owner.settings.cleanuprules.preview.overview = Заплановано видалити %d пакунків. [secrets] deletion = Видалити секрет @@ -3662,10 +3628,6 @@ runners.update_runner_success = Ранер оновлено runners.delete_runner_header = Підтвердіть видалення ранера runners.status.offline = Неактивний runners.status.idle = Простоює -runs.invalid_workflow_helper = Недійсний файл конфігурації робочого потоку. Будь ласка, перевірте файл конфігурації: %s -runs.no_job = Робочий потік повинен містити принаймні одне завдання -workflow.dispatch.use_from = Використати робочий потік із -runs.no_job_without_needs = Робочий потік повинен містити принаймні одне завдання без залежностей. @@ -3678,7 +3640,7 @@ deleted.display_name = Видалений проєкт [git.filemode] symbolic_link=Символічне посилання -directory = Каталог +directory = Тека submodule = Підмодуль normal_file = Звичайний файл executable_file = Виконуваний файл diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index d87ad53676..acdd4c0ced 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -171,7 +171,7 @@ copy_path = 复制路径 [aria] navbar=导航栏 footer=页脚 -footer.software=关于此软件 +footer.software=关于软件 footer.links=链接 [heatmap] @@ -1062,8 +1062,8 @@ language.description = 此语言将保存到您的账号中,并在您登录后 language.localization_project = 帮助我们将 Forgejo 翻译成您的语言!了解更多。 user_block_yourself = 您不能屏蔽自己。 pronouns_custom_label = 自定义代词 -change_username_redirect_prompt.with_cooldown.one = 旧用户名将在 %[1]d 天的保护期后对所有人可用,您仍可以在此期间重新认领旧用户名。 -change_username_redirect_prompt.with_cooldown.few = 旧用户名将在 %[1]d 天的保护期后对所有人可用,您仍可以在此期间重新认领旧用户名。 +change_username_redirect_prompt.with_cooldown.one = 旧的用户名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧的用户名。 +change_username_redirect_prompt.with_cooldown.few = 旧的用户名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧的用户名。 keep_pronouns_private = 仅向已认证用户显示代词 keep_pronouns_private.description = 这将对未登录的访问者隐藏您的代词。 quota = 配额 @@ -1581,7 +1581,7 @@ issues.remove_ref_at=`删除了引用 %s %s` issues.add_ref_at=`添加了引用 %s %s` issues.delete_branch_at=`于 %[2]s 删除了分支 %[1]s` issues.filter_label=标签筛选 -issues.filter_label_exclude=使用 Alt + 单击 排除标签 +issues.filter_label_exclude=`使用 alt + 鼠标左键 / 回车 排除标签` issues.filter_label_no_select=所有标签 issues.filter_label_select_no_label=无标签 issues.filter_milestone=里程碑筛选 @@ -1655,13 +1655,13 @@ issues.close_comment_issue=评论并关闭 issues.reopen_issue=重新开放 issues.reopen_comment_issue=重新打开并评论 issues.create_comment=评论 -issues.closed_at=`于 %s 关闭了此议题` -issues.reopened_at=`于 %s 重新打开了此议题` -issues.commit_ref_at=`于 %s 从提交中引用了此议题` -issues.ref_issue_from=`引用了此议题 %[3]s %[1]s` -issues.ref_pull_from=`引用了此合并请求 %[3]s %[1]s` -issues.ref_closing_from=`于 %[1]s 从合并请求 %[3]s 引用了此议题,将关闭此议题` -issues.ref_reopening_from=`于 %[1]s 从合并请求 %[3]s 引用了此议题,将重新打开此议题 ` +issues.closed_at=`于%[2]s关闭此议题` +issues.reopened_at=`重新打开此问题 %[2]s` +issues.commit_ref_at=`于%[2]s在代码提交中引用了该议题` +issues.ref_issue_from=`引用了议题 %[4]s %[2]s` +issues.ref_pull_from=`引用了合并请求 %[4]s %[2]s` +issues.ref_closing_from=`于 %[2]s 从合并请求 %[4]s引用了此议题,将关闭此议题` +issues.ref_reopening_from=`于 %[2]s 引用了合并请求 %[4]s 将重新讨论此议题 ` issues.ref_closed_from=`关闭了这个议题 %[4]s %[2]s` issues.ref_reopened_from=`重新打开这个议题 %[4]s %[2]s` issues.ref_from=`来自 %[1]s` @@ -1969,8 +1969,8 @@ pulls.update_branch_success=分支更新成功 pulls.update_not_allowed=您无权更新分支 pulls.outdated_with_base_branch=此分支相比基础分支已过期 pulls.close=关闭 -pulls.closed_at=`于 %s 关闭了此合并请求 ` -pulls.reopened_at=`于 %s 重新打开了此合并请求` +pulls.closed_at=`于%[2]s关闭此合并请求 ` +pulls.reopened_at=`重新打开此合并请求 %[2]s` pulls.cmd_instruction_hint=查看命令行说明 pulls.cmd_instruction_checkout_title=检出 pulls.cmd_instruction_checkout_desc=从你的仓库中检出一个新的分支并测试变更。 @@ -2770,7 +2770,7 @@ settings.wiki_rename_branch_main = 标准化百科分支名称 settings.wiki_rename_branch_main_notices_1 = 此操作无法撤消。 settings.wiki_branch_rename_success = 百科仓库的分支名称已成功规范化。 settings.confirm_wiki_branch_rename = 重命名百科分支 -pulls.commit_ref_at = `于 %s 从提交中引用了此合并请求` +pulls.commit_ref_at = `在提交 %[2]s 中引用了此合并请求` settings.wiki_rename_branch_main_notices_2 = 这将永久重命名 %s 的仓库百科的内部分支。现存的检出方式需要更新。 settings.wiki_branch_rename_failure = 无法标准化仓库百科的分支名称。 settings.add_collaborator_blocked_our = 因仓库所有者已将其拉黑,不能添加该用户为协作者。 @@ -2922,7 +2922,6 @@ settings.event_action_success = 成功 settings.event_action_success_desc = Action运行以成功结束。 settings.event_action_failure_desc = Action运行以失败结束。 settings.event_header_action = Action运行事件 -issues.filter_type.all_pull_requests = 所有合并请求 [graphs] component_loading=正在加载 %s… @@ -3058,8 +3057,8 @@ teams.invite.by=邀请人 %s teams.invite.description=请点击下面的按钮加入团队。 follow_blocked_user = 你无法关注此组织,因为此组织已屏蔽你。 open_dashboard = 打开仪表盘 -settings.change_orgname_redirect_prompt.with_cooldown.one = 旧组织名将在 %[1]d 天的保护期后对所有人可用,您仍可以在此期间重新认领旧名称。 -settings.change_orgname_redirect_prompt.with_cooldown.few = 旧组织名将在 %[1]d 天的保护期后对所有人可用,您仍可以在此期间重新认领旧名称。 +settings.change_orgname_redirect_prompt.with_cooldown.one = 旧的组织名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧的名字。 +settings.change_orgname_redirect_prompt.with_cooldown.few = 旧的组织名将在%[1]d天的保护期后对所有人可用,您仍可以在此期间重新认领旧名字。 [admin] dashboard=管理面板 diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini index 45534801de..e2cb0d8b2c 100644 --- a/options/locale/locale_zh-HK.ini +++ b/options/locale/locale_zh-HK.ini @@ -574,7 +574,7 @@ issues.delete_comment_confirm=您確定要刪除該條評論嗎? issues.context.edit=編輯 issues.reopen_issue=重新開啟 issues.create_comment=評論 -issues.commit_ref_at=`在代碼提交 %s 中引用了該問題` +issues.commit_ref_at=`在代碼提交 %[2]s 中引用了該問題` issues.role.owner=管理員 issues.role.member=普通成員 issues.sign_in_require_desc= 登入 才能加入這對話。 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index fba51a391e..b21e4c8f79 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -1604,13 +1604,13 @@ issues.close_comment_issue=留言並關閉 issues.reopen_issue=重新開放 issues.reopen_comment_issue=留言並重新開放 issues.create_comment=留言 -issues.closed_at=`關閉了這個問題 %s` -issues.reopened_at=`重新開放了這個問題 %s` -issues.commit_ref_at=`在提交中關聯了這個問題 %s` -issues.ref_issue_from=`關聯了這個問題 %[3]s %[1]s` -issues.ref_pull_from=`關聯了這個合併請求 %[3]s %[1]s` -issues.ref_closing_from=從將關閉此問題的拉取請求 %[3]s 中提及了此問題,%[1]s -issues.ref_reopening_from=從將重新開啟此問題的拉取請求 %[3]s 中提及了此問題,%[1]s +issues.closed_at=`關閉了這個問題 %[2]s` +issues.reopened_at=`重新開放了這個問題 %[2]s` +issues.commit_ref_at=`在提交中關聯了這個問題 %[2]s` +issues.ref_issue_from=`關聯了這個問題 %[4]s %[2]s` +issues.ref_pull_from=`關聯了這個合併請求 %[4]s %[2]s` +issues.ref_closing_from=從將關閉此問題的拉取請求 %[4]s 中提及了此問題%[2]s +issues.ref_reopening_from=從將重新開啟此問題的拉取請求 %[4]s 中提及了此問題%[2]s issues.ref_closed_from=`關閉了這個問題 %[4]s %[2]s` issues.ref_reopened_from=`重新開放了這個問題 %[4]s %[2]s` issues.ref_from=`自 %[1]s` @@ -1879,8 +1879,8 @@ pulls.update_branch_success=分支更新成功 pulls.update_not_allowed=您無權更新分支 pulls.outdated_with_base_branch=相對於基底分支,此分支已過時 pulls.close=關閉合併請求 -pulls.closed_at=`關閉了這個合併請求 %s` -pulls.reopened_at=`重新開放了這個合併請求 %s` +pulls.closed_at=`關閉了這個合併請求 %[2]s` +pulls.reopened_at=`重新開放了這個合併請求 %[2]s` pulls.clear_merge_message=清除合併訊息 pulls.clear_merge_message_hint=清除合併訊息將僅移除提交訊息內容,留下產生的 git 結尾,如「Co-Authored-By …」。 @@ -2634,7 +2634,7 @@ commits.search_branch = 此分支 commits.browse_further = 進一步瀏覽 commits.renamed_from = 自 %s 重新命名 issues.filter_milestone_none = 沒有里程碑 -issues.num_comments_1 = %d 則留言 +issues.num_comments_1 = %s 則留言 issues.no_content = 沒有提供敘述。 settings.new_owner_blocked_doer = 新的所有者已封鎖您。 new_repo_helper = 一個儲存庫包含專案的所有檔案和它們的修訂歷史。在別處已經有儲存庫了嗎?遷移儲存庫。 @@ -2693,7 +2693,7 @@ signing.wont_sign.never = 永不簽署提交。 editor.push_out_of_date = 該推送似乎過期了。 issues.cancel_tracking_history = `已取消時間追蹤 %s` issues.due_date_not_writer = 您需要有寫入這個儲存庫的權限才能更新其問題的到期日。 -pulls.commit_ref_at = `在提交 %s 引用了這個合併請求` +pulls.commit_ref_at = `在提交 %[2]s 引用了這個合併請求` pulls.cmd_instruction_checkout_desc = 從您的專案儲存庫中,建立並切換到一個新分支以測試這些變更。 pulls.cmd_instruction_merge_title = 合併 pulls.ready_for_review = 可以開始審閱了嗎? diff --git a/options/locale_next/locale_cs-CZ.json b/options/locale_next/locale_cs-CZ.json index 24380bea1b..97a8536d4f 100644 --- a/options/locale_next/locale_cs-CZ.json +++ b/options/locale_next/locale_cs-CZ.json @@ -105,11 +105,5 @@ "settings.visibility.description": "Viditelnost profilu ovlivňuje možnost ostatních přistupovat k vašim veřejným repozitářům. Zjistit více", "avatar.constraints_hint": "Velikost vlastního avataru nesmí překročit %[1]s nebo být větší než %[2]dx%[3]d pixelů", "repo.diff.commit.next-short": "Další", - "repo.diff.commit.previous-short": "Předchozí", - "profile.actions.tooltip": "Další akce", - "keys.gpg.link": "Klíče GPG", - "profile.edit.link": "Upravit profil", - "feed.atom.link": "Zdroj Atom", - "keys.ssh.link": "Klíče SSH", - "og.repo.summary_card.alt_description": "Karta se souhrnem repozitáře %[1]s, popsaným jako: %[2]s" + "repo.diff.commit.previous-short": "Předchozí" } diff --git a/options/locale_next/locale_de-DE.json b/options/locale_next/locale_de-DE.json index d256c54dc6..94ab12f180 100644 --- a/options/locale_next/locale_de-DE.json +++ b/options/locale_next/locale_de-DE.json @@ -97,11 +97,5 @@ "settings.visibility.description": "Die Profilsichtbarkeit beeinflusst die Möglichkeit anderer, auf deine nicht-privaten Repositorys zuzugreifen. Erfahre mehr", "avatar.constraints_hint": "Individuelles Profilbild darf %[1]s in der Größe nicht überschreiten, und nicht größer als %[2]dx%[3]d Pixel sein", "repo.diff.commit.next-short": "Nächste", - "repo.diff.commit.previous-short": "Vorherige", - "profile.edit.link": "Profil bearbeiten", - "feed.atom.link": "Atom-Feed", - "keys.ssh.link": "SSH-Schlüssel", - "keys.gpg.link": "GPG-Schlüssel", - "profile.actions.tooltip": "Mehr Aktionen", - "og.repo.summary_card.alt_description": "Zusammenfassungskarte des Repositorys %[1]s, beschrieben als %[2]s" + "repo.diff.commit.previous-short": "Vorherige" } diff --git a/options/locale_next/locale_en-US.json b/options/locale_next/locale_en-US.json index a551db87dc..b1c98e4551 100644 --- a/options/locale_next/locale_en-US.json +++ b/options/locale_next/locale_en-US.json @@ -102,6 +102,5 @@ "admin.dashboard.cleanup_offline_runners": "Cleanup offline runners", "settings.visibility.description": "Profile visibility affects others' ability to access your non-private repositories. Learn more", "avatar.constraints_hint": "Custom avatar may not exceed %[1]s in size or be larger than %[2]dx%[3]d pixels", - "og.repo.summary_card.alt_description": "Summary card of repository %[1]s, described as: %[2]s", "meta.last_line": "Thank you for translating Forgejo! This line isn't seen by the users but it serves other purposes in the translation management. You can place a fun fact in the translation instead of translating it." } diff --git a/options/locale_next/locale_fil.json b/options/locale_next/locale_fil.json index 84b537fbdc..1f1e535dad 100644 --- a/options/locale_next/locale_fil.json +++ b/options/locale_next/locale_fil.json @@ -21,7 +21,7 @@ "alert.asset_load_failed": "Nabigong i-load ang mga asset file mula sa {path}. Siguraduhin na maa-access ang mga asset file.", "install.invalid_lfs_path": "Nabigong gawin ang LFS root sa tinakdang path: %[1]s", "alert.range_error": " dapat ay numero sa pagitan ng %[1]s at %[2]s.", - "meta.last_line": "Every day, I imagine a future where I can be with you. In my hand is a pen that will write a poem of me and you. The ink flows down into a dark puddle... Just move your hand, write the way into his heart. But in this world of infinite choices. What will it take just to find that special day? Have I found everybody a fun assignment to do today? When you're here, everything that we do is fun for them anyway... When I can't even read my own feelings. What good are words when a smile says it all? And if this world won't write me an ending... What will it take just for me to have it all? Does my pen only write bitter words for those who are dear to me? Is it love if I take you, or is it love if I set you free? The ink flows down into a dark puddle... How can I write love into reality? If I can't hear the sound of your heartbeat What do you call love in your reality? And in your reality, if I don't know how to love you... I'll leave you be.", + "meta.last_line": "Sayori... I love you. — MC from Doki Doki Literature Club", "mail.actions.successful_run_after_failure": "Na-recover ang workflow na %[1]s sa repositoryong %[2]s", "mail.actions.not_successful_run": "Nabigo ang workflow na %[1]s sa repositoryong %[2]s", "mail.actions.run_info_previous_status": "Nakaraang Status ng Run: %[1]s", @@ -94,14 +94,5 @@ "editor.textarea.tab_hint": "Naka-indent na ang linya. Pindutin ulit ang Tab o Escape para umalis sa editor.", "editor.textarea.shift_tab_hint": "Walang indentation sa linyang ito. Pindutin ang Shift + Tab ulit o Escape para umalis sa editor.", "admin.dashboard.cleanup_offline_runners": "Linisin ang mga offline na runner", - "settings.visibility.description": "Maaapektuhan ng visibility ng profile ang kakayahan ng iba na i-access ang iyong mga hindi pribadong repositoryo. Matuto pa", - "avatar.constraints_hint": "Hindi maaaring lumagpas sa laking %[1]s o mas malaki sa %[2]dx%[3]d pixel ang custom na avatar", - "repo.diff.commit.next-short": "Susunod", - "repo.diff.commit.previous-short": "Nakaraan", - "profile.edit.link": "I-edit ang profile", - "feed.atom.link": "Atom feed", - "keys.ssh.link": "Mga SSH key", - "keys.gpg.link": "Mga GPG key", - "profile.actions.tooltip": "Higit pang mga aksyon", - "og.repo.summary_card.alt_description": "Card ng pangkalahatang ideya ng repositoryong %[1]s, inilalarawan bilang: %[2]s" + "settings.visibility.description": "Maaapektuhan ng visibility ng profile ang kakayahan ng iba na i-access ang iyong mga hindi pribadong repositoryo. Matuto pa" } diff --git a/options/locale_next/locale_fr-FR.json b/options/locale_next/locale_fr-FR.json index da26d56107..a9035f0848 100644 --- a/options/locale_next/locale_fr-FR.json +++ b/options/locale_next/locale_fr-FR.json @@ -6,7 +6,7 @@ }, "repo.pulls.title_desc": { "one": "veut fusionner %[1]d commit depuis %[2]s vers %[3]s", - "many": "veut fusionner %[1]d commits depuis %[2]s vers %[3]s", + "many": "souhaite fusionner %[1]d révision(s) depuis %[2]s vers %[3]s", "other": "" }, "search.milestone_kind": "Recherche dans les jalons…", diff --git a/options/locale_next/locale_it-IT.json b/options/locale_next/locale_it-IT.json index 8464d6244e..8bd6d811a0 100644 --- a/options/locale_next/locale_it-IT.json +++ b/options/locale_next/locale_it-IT.json @@ -15,83 +15,5 @@ "home.welcome.no_activity": "Nessun'attività", "home.explore_repos": "Esplora i repositori", "home.explore_users": "Esplora l'utenza", - "home.explore_orgs": "Esplora le organizzazioni", - "mail.actions.successful_run_after_failure_subject": "Il flusso di lavoro %[1] ha ripreso a funzionare nel repositorio %[2]s", - "mail.actions.not_successful_run_subject": "Il flusso di lavoro %[1]s è fallito nel repositorio %[2]s", - "relativetime.future": "nel futuro", - "relativetime.days": { - "one": "ieri", - "many": "%d giorni fa", - "other": "%d giorni fa" - }, - "relativetime.1day": "ieri", - "repo.form.cannot_create": "Tutti gli spazi in cui puoi creare repositori hanno raggiunto il limite di repositori.", - "discussion.locked": "Questa discussione è stata bloccata. Solo i contributori possono commentare.", - "relativetime.hours": { - "one": "un'ora fa", - "many": "%d ore fa", - "other": "%d ore fa" - }, - "relativetime.2years": "due anni fa", - "relativetime.now": "adesso", - "relativetime.weeks": { - "one": "una settimana fa", - "many": "%d settimane fa", - "other": "%d settimane fa" - }, - "relativetime.months": { - "one": "un mese fa", - "many": "%d mesi fa", - "other": "%d mesi fa" - }, - "relativetime.years": { - "one": "un anno fa", - "many": "%d anni fa", - "other": "%d anni fa" - }, - "repo.issue_indexer.title": "Indicizzatore delle segnalazioni", - "admin.config.moderation_config": "Impostazioni di moderazione", - "moderation.report_abuse": "Segnala abuso", - "moderation.report_content": "Segnala contenuto", - "moderation.report_abuse_form.already_reported": "Hai già segnalato questo contenuto", - "moderation.abuse_category": "Categoria", - "moderation.abuse_category.placeholder": "Seleziona una categoria", - "moderation.abuse_category.spam": "Spam", - "moderation.abuse_category.malware": "Malware", - "moderation.abuse_category.illegal_content": "Contenuti illegali", - "moderation.abuse_category.other_violations": "Altre violazioni delle regole della piattaforma", - "moderation.report_remarks": "Note aggiuntive", - "moderation.report_remarks.placeholder": "Aggiungi dettagli riguardanti l'abuso che stai segnalando.", - "moderation.submit_report": "Invia segnalazione", - "error.not_found.title": "Pagina non trovata", - "themes.names.forgejo-auto": "Forgejo (segui le impostazioni di sistema)", - "stars.list.none": "Nessuno ha messo una stella a questo repo.", - "watch.list.none": "Nessuno sta osservando questo repo.", - "followers.incoming.list.self.none": "Nessuno sta seguendo il tuo profilo.", - "followers.incoming.list.none": "Nessuno sta seguendo questo utente.", - "followers.outgoing.list.self.none": "Non segui nessuno.", - "followers.outgoing.list.none": "%s non sta seguendo nessuno.", - "relativetime.2days": "due giorni fa", - "relativetime.2weeks": "due settimane fa", - "relativetime.1week": "la settimana scorsa", - "relativetime.1month": "il mese scorso", - "relativetime.2months": "due mesi fa", - "relativetime.1year": "l'anno scorso", - "moderation.report_abuse_form.header": "Segnala abuso all'amministratore", - "moderation.report_abuse_form.details": "Questo modulo dovrebbe essere utilizzato per segnalare utenti che creano profili, repositori, segnalazioni o commenti spam o che si comportano in modo non adeguato.", - "moderation.report_abuse_form.invalid": "Argomenti non validi", - "moderation.reporting_failed": "Impossibile inviare segnalazione: %v", - "moderation.reported_thank_you": "Grazie per la segnalazione. L'amministratore è stato avvertito.", - "mail.actions.run_info_ref": "Ramo: %[1]s (%[2]s)", - "alert.asset_load_failed": "Impossibile caricare i file di risorsa da {path}. Controlla che i file di risorsa siano accessibili.", - "install.invalid_lfs_path": "Non è possibile creare una root LFS nel percorso specificato: %[1]s", - "home.welcome.activity_hint": "Non c'è nulla nel tuo feed. Le tue azioni e le attività dei repositori che segui verranno mostrate qui.", - "relativetime.mins": { - "one": "un minuto fa", - "many": "%d minuti fa", - "other": "%d minuti fa" - }, - "editor.textarea.tab_hint": "Linea già indentata. Premi di nuovo Tab o Esc per uscire dall'editor.", - "repo.diff.commit.previous-short": "Precedente", - "meta.last_line": "Ambaraba cicci cocco." + "home.explore_orgs": "Esplora le organizzazioni" } diff --git a/options/locale_next/locale_lv-LV.json b/options/locale_next/locale_lv-LV.json index 4deae220bf..f71cfa227d 100644 --- a/options/locale_next/locale_lv-LV.json +++ b/options/locale_next/locale_lv-LV.json @@ -105,11 +105,5 @@ "settings.visibility.description": "Profila redzamība ietekmē iespēju citiem piekļūt Tavām glabātavām, kas nav privātas. Uzzināt vairāk", "avatar.constraints_hint": "Pielāgots profila attēls nevar pārsniegt %[1]s vai būt lielāks par %[2]dx%[3]d pikseļiem", "repo.diff.commit.next-short": "Nāk.", - "repo.diff.commit.previous-short": "Iepr.", - "profile.actions.tooltip": "Vairāk darbību", - "profile.edit.link": "Labot profilu", - "feed.atom.link": "Atom barotne", - "keys.ssh.link": "SSH atslēgas", - "keys.gpg.link": "GPG atslēgas", - "og.repo.summary_card.alt_description": "Glabātavas %[1]s kopsavilkuma kartīte, aprakstīta kā: %[2]s" + "repo.diff.commit.previous-short": "Iepr." } diff --git a/options/locale_next/locale_nb_NO.json b/options/locale_next/locale_nb_NO.json index 3349e136b5..0967ef424b 100644 --- a/options/locale_next/locale_nb_NO.json +++ b/options/locale_next/locale_nb_NO.json @@ -1,107 +1 @@ -{ - "relativetime.1day": "i går", - "moderation.abuse_category.other_violations": "Andre regel overtredelser", - "moderation.report_remarks": "Kommentar", - "moderation.report_remarks.placeholder": "Skriv noen detaljer rundt missbruket du rapporterer.", - "moderation.submit_report": "Send rapport", - "moderation.reporting_failed": "Missbruk rapporten kunne ikke sendes inn: %v", - "relativetime.hours": { - "one": "%d time siden", - "other": "%d timer siden" - }, - "repo.form.cannot_create": "Det maksimale antallet repositories er nådd i alle områdene du har tilgang til.", - "repo.issue_indexer.title": "Saksindekserer", - "moderation.abuse_category.illegal_content": "Ulovlig innhold", - "error.not_found.title": "Fant ikke siden", - "themes.names.forgejo-light": "Forgejo lyst", - "themes.names.forgejo-dark": "Forgejo mørk", - "stars.list.none": "Ingen har gitt stjerner til dette repoet.", - "watch.list.none": "Ingen følger dette repoet.", - "followers.incoming.list.none": "Ingen følger denne brukeren.", - "followers.outgoing.list.self.none": "Du følger ikke noen.", - "followers.outgoing.list.none": "%s følger ikke noen.", - "relativetime.2days": "to dager siden", - "relativetime.1week": "forrige uke", - "relativetime.2weeks": "to uker siden", - "relativetime.1month": "forrige måned", - "relativetime.2months": "to måneder siden", - "relativetime.1year": "i fjor", - "relativetime.2years": "to år siden", - "alert.asset_load_failed": "Kunne ikke laste inn ressursfiler fra {path}. Sørg for at ressursfilene er tilgjengelige.", - "search.milestone_kind": "Søker i milepæler…", - "home.welcome.no_activity": "Ingen aktivitet", - "home.explore_repos": "Utforsk repositorier", - "home.explore_users": "Utforsk brukere", - "home.explore_orgs": "Utforsk organisasjoner", - "relativetime.mins": { - "one": "%d minutt siden", - "other": "%d minutter siden" - }, - "relativetime.months": { - "one": "%d måned siden", - "other": "%d måneder siden" - }, - "relativetime.years": { - "one": "%d år siden", - "other": "%d år siden" - }, - "repo.pulls.title_desc": { - "one": "ønsker å slå sammen %[1]d commit fra %[2]s inn i %[3]s", - "other": "ønsker å slå sammen %[1]d commits fra %[2]s inn i %[3]s" - }, - "og.repo.summary_card.alt_description": "Sammendrag for repository %[1]s, beskrevet som: %[2]s", - "followers.incoming.list.self.none": "Ingen følger profilen din.", - "install.invalid_lfs_path": "Kan ikke opprette LFS-root på: %[1]s", - "relativetime.now": "nå", - "relativetime.future": "i fremtiden", - "repo.pulls.merged_title_desc": { - "one": "slo sammen %[1]d commit fra %[2]s inn i %[3]s %[4]s", - "other": "slo sammen %[1]d commits fra %[2]s inn i %[3]s %[4]s" - }, - "editor.textarea.tab_hint": "Linjen er allerede innrykket. Trykk Tab igjen eller trykk Escape for å gå ut av editoren.", - "editor.textarea.shift_tab_hint": "Ingen innrykk på denne linjen. Trykk Shift + Tab igjen eller Escape for å gå ut av editoren.", - "alert.range_error": " må være et nummer mellom %[1]s og %[2]s.", - "themes.names.forgejo-auto": "Forgejo (følg systemtema)", - "home.welcome.activity_hint": "Det er foreløpig ingenting i feeden din. Aktivitetene dine og handlingene dine fra repositorier du følger, vil vises her etter hvert.", - "incorrect_root_url": "Denne Forgejo instansen er konfigurert til å bruke \"%s\". Du bruker Forgejo via en annen URL, noe som kan forårsake at deler av applikasjonen ikke fungerer. Den kanoniske URL-en styres av Forgejo-administratorer via innstillingen ROOT_URL i app.ini-filen.", - "mail.actions.run_info_trigger": "Startet på grunn av: %[1]s by: %[2]s", - "admin.dashboard.cleanup_offline_runners": "Rydd opp offline runners", - "settings.visibility.description": "Profilens synlighet påvirker andres mulighet til å få tilgang til dine ikke-private repositorier. Les mer", - "profile.actions.tooltip": "Flere handlinger", - "profile.edit.link": "Rediger profil", - "relativetime.days": { - "one": "%d dag siden", - "other": "%d dager siden" - }, - "relativetime.weeks": { - "one": "%d uke siden", - "other": "%d uker siden" - }, - "feed.atom.link": "Atom feed", - "keys.ssh.link": "SSH nøkler", - "keys.gpg.link": "GPG nøkler", - "admin.config.moderation_config": "Moderasjonskonfigurasjon", - "moderation.report_abuse": "Rapporter missbruk", - "moderation.report_content": "Rapporter innhold", - "moderation.report_abuse_form.header": "Rapporter missbruk til en administrator", - "moderation.report_abuse_form.details": "Denne formen skal brukes for å rapporterer brukere som oppretter spam profiler, repositorier, saker, kommentarer eller oppfører seg upassende.", - "moderation.report_abuse_form.invalid": "Ugyldige argumenter", - "moderation.report_abuse_form.already_reported": "Du har allerede rapportert dette innholdet", - "moderation.abuse_category": "Kategori", - "moderation.abuse_category.placeholder": "Velg en kategori", - "moderation.abuse_category.spam": "Spam", - "moderation.abuse_category.malware": "Skadelig programvare", - "moderation.reported_thank_you": "Takk for meldingen. Vi har varslet administratorene.", - "mail.actions.successful_run_after_failure_subject": "Arbeidsflyten %[1]s er gjenopprettet i repository %[2]s", - "mail.actions.not_successful_run_subject": "Arbeidsflyten %[1]s feilet i repository %[2]s", - "mail.actions.successful_run_after_failure": "Arbeidsflyten %[1]s er gjenopprettet i repository %[2]s", - "mail.actions.not_successful_run": "Arbeidsflyten %[1]s feilet i repository %[2]s", - "mail.actions.run_info_cur_status": "Status for denne kjøringen: %[1]s (oppdatert fra %[2]s)", - "mail.actions.run_info_previous_status": "Status for forrige kjøring: %[1]s", - "mail.actions.run_info_ref": "Branch: %[1]s (%[2]s)", - "repo.diff.commit.next-short": "Neste", - "repo.diff.commit.previous-short": "Forrige", - "discussion.locked": "Denne diskusjonen er låst. Kommentarer kan kun gjøres av bidragsytere.", - "avatar.constraints_hint": "Egendefinert avatar kan ikke overstige %[1]s i størrelse eller være større enn %[2]d × %[3]d piksler", - "meta.last_line": "Vi gir oss ikke. Kongen har sagt nei!" -} +{} diff --git a/options/locale_next/locale_nds.json b/options/locale_next/locale_nds.json index 207a138926..9a3884a87f 100644 --- a/options/locale_next/locale_nds.json +++ b/options/locale_next/locale_nds.json @@ -97,11 +97,5 @@ "settings.visibility.description": "De Profil-Sichtbaarkeid maakt daar wat an, of un wo anner Lüü diene nich-privaaten Repositoriums ankieken könen. Mehr unnerhören", "avatar.constraints_hint": "Dat eegene Kontobill düür nich groter as %[1]s wesen of groter as %[2]d×%[3]d Billtüttels wesen", "repo.diff.commit.next-short": "Anner", - "repo.diff.commit.previous-short": "Vörig", - "feed.atom.link": "Atom-Schuuv", - "keys.ssh.link": "SSH-Slötels", - "keys.gpg.link": "GPG-Slötels", - "profile.actions.tooltip": "Mehr Aktioonen", - "profile.edit.link": "Profil bewarken", - "og.repo.summary_card.alt_description": "Tosamenfatens-Kaart vun de Repositorium %[1]s, beschrieven as: %[2]s" + "repo.diff.commit.previous-short": "Vörig" } diff --git a/options/locale_next/locale_nl-NL.json b/options/locale_next/locale_nl-NL.json index 5df7db2b9d..4f109825aa 100644 --- a/options/locale_next/locale_nl-NL.json +++ b/options/locale_next/locale_nl-NL.json @@ -92,16 +92,5 @@ "watch.list.none": "Niemand houdt deze repo in de gaten.", "followers.incoming.list.self.none": "Niemand volgt uw profiel.", "followers.incoming.list.none": "Deze gebruiker wordt door niemand gevolgd.", - "followers.outgoing.list.self.none": "U volgt niemand.", - "settings.visibility.description": "Profielzichtbaarheid beïnvloedt de mogelijkheid van anderen om toegang te krijgen tot je niet-privé repositories. Lees meer", - "repo.diff.commit.next-short": "Volgende", - "admin.dashboard.cleanup_offline_runners": "Offline runners opruimen", - "keys.ssh.link": "SSH sleutels", - "keys.gpg.link": "GPG sleutels", - "profile.actions.tooltip": "Meer acties", - "profile.edit.link": "Profiel bewerken", - "feed.atom.link": "Atom-feed", - "repo.diff.commit.previous-short": "Vorige", - "avatar.constraints_hint": "Eigen avatars mogen niet groter zijn dan %[1]s in grootte of groter zijn dan %[2]dx%[3]d pixels", - "og.repo.summary_card.alt_description": "Samenvattingsoverzicht van repositorie %[1]s, omschreven als: %[2]s" + "followers.outgoing.list.self.none": "U volgt niemand." } diff --git a/options/locale_next/locale_pt-BR.json b/options/locale_next/locale_pt-BR.json index 336dd5a484..92e140878e 100644 --- a/options/locale_next/locale_pt-BR.json +++ b/options/locale_next/locale_pt-BR.json @@ -103,13 +103,5 @@ "editor.textarea.shift_tab_hint": "Sem indentação nesta linha. Pressione Shift + Tab novamente ou Esc para sair do editor.", "admin.dashboard.cleanup_offline_runners": "Limpar runners desconectados", "avatar.constraints_hint": "Imagem de perfil personalizada não pode exceder %[1]s em tamanho ou ser maior que %[2]dx%[3]d pixels", - "settings.visibility.description": "A visibilidade do perfil afeta a habilidade de acessarem seus repositórios não-privados. Saiba mais", - "repo.diff.commit.next-short": "Próximo", - "repo.diff.commit.previous-short": "Anterior", - "profile.edit.link": "Editar perfil", - "feed.atom.link": "Feed Atom", - "keys.gpg.link": "Chaves GPG", - "og.repo.summary_card.alt_description": "Cartão de resumo do repositório %[1]s, descrito como: %[2]s", - "profile.actions.tooltip": "Mais Actions", - "keys.ssh.link": "Chaves SSH" + "settings.visibility.description": "A visibilidade do perfil afeta a habilidade de acessarem seus repositórios não-privados. Saiba mais" } diff --git a/options/locale_next/locale_pt-PT.json b/options/locale_next/locale_pt-PT.json index a0caa90b68..78e6dc4493 100644 --- a/options/locale_next/locale_pt-PT.json +++ b/options/locale_next/locale_pt-PT.json @@ -103,12 +103,5 @@ "stars.list.none": "Ninguém juntou este repositório aos favoritos.", "admin.dashboard.cleanup_offline_runners": "Limpeza de executores offline", "settings.visibility.description": "A visibilidade do perfil afecta a capacidade de outros acederem aos seus repositórios não privados. Ler mais", - "avatar.constraints_hint": "O avatar personalizado não pode exceder %[1]s de tamanho ou ser maior do que %[2]dx%[3]d pixéis", - "repo.diff.commit.next-short": "Seg.", - "profile.actions.tooltip": "Mais Actions", - "profile.edit.link": "Editar perfil", - "feed.atom.link": "Feed Atom", - "keys.ssh.link": "Chaves SSH", - "keys.gpg.link": "Chaves GPG", - "repo.diff.commit.previous-short": "Ant." + "avatar.constraints_hint": "O avatar personalizado não pode exceder %[1]s de tamanho ou ser maior do que %[2]dx%[3]d pixéis" } diff --git a/options/locale_next/locale_ru-RU.json b/options/locale_next/locale_ru-RU.json index 922e2612af..8992cc6abd 100644 --- a/options/locale_next/locale_ru-RU.json +++ b/options/locale_next/locale_ru-RU.json @@ -23,7 +23,7 @@ "alert.asset_load_failed": "Не удалось получить ресурсы из {path}. Убедитесь, что файлы ресурсов доступны.", "install.invalid_lfs_path": "Не удалось расположить корень LFS по указанному пути: %[1]s", "alert.range_error": " - число должно быть в диапазоне от %[1]s-%[2]s.", - "meta.last_line": "Unskip..", + "meta.last_line": "Unskip.", "mail.actions.not_successful_run_subject": "Провал раб. потока %[1]s в репозитории %[2]s", "mail.actions.successful_run_after_failure_subject": "Возобновление раб. потока %[1]s в репозитории %[2]s", "mail.actions.run_info_ref": "Ветвь: %[1]s (%[2]s)", @@ -104,11 +104,6 @@ "admin.dashboard.cleanup_offline_runners": "Удалить недоступных исполнителей", "avatar.constraints_hint": "Изображение профиля не может быть более %[1]s и крупнее %[2]dx%[3]d пикселей", "settings.visibility.description": "Видимость профиля влияет на доступ других до ваших не частных репозиториев. Подробнее", - "repo.diff.commit.previous-short": "Пред.", - "repo.diff.commit.next-short": "След.", - "profile.actions.tooltip": "Показать действия", - "feed.atom.link": "Atom-лента", - "keys.ssh.link": "Ключи SSH", - "keys.gpg.link": "Ключи GPG", - "profile.edit.link": "Изменить профиль" + "repo.diff.commit.previous-short": "Предыдущий", + "repo.diff.commit.next-short": "Далее" } diff --git a/options/locale_next/locale_sv-SE.json b/options/locale_next/locale_sv-SE.json index 3bc37deff8..9a8762212c 100644 --- a/options/locale_next/locale_sv-SE.json +++ b/options/locale_next/locale_sv-SE.json @@ -95,13 +95,5 @@ "moderation.abuse_category.spam": "Skräppost", "moderation.abuse_category.malware": "Skadlig kod", "settings.visibility.description": "Profilens synlighet påverkar andras möjlighet att komma åt dina icke-privata förråd. Läs mer", - "avatar.constraints_hint": "Anpassade avatarer får inte vara större än %[1] eller %[2]dx%[3] bildpunkter", - "og.repo.summary_card.alt_description": "Sammanfattningskort för arkivet %[1]s, beskrivet som: %[2]s", - "profile.actions.tooltip": "Fler åtgärder", - "keys.gpg.link": "GPG-nycklar", - "profile.edit.link": "Redigera profil", - "keys.ssh.link": "SSH-nycklar", - "repo.diff.commit.next-short": "Nästa", - "repo.diff.commit.previous-short": "Föreg", - "feed.atom.link": "Atom-flöde" + "avatar.constraints_hint": "Anpassade avatarer får inte vara större än %[1] eller %[2]dx%[3] bildpunkter" } diff --git a/options/locale_next/locale_uk-UA.json b/options/locale_next/locale_uk-UA.json index af219b50d0..c3bcf5397c 100644 --- a/options/locale_next/locale_uk-UA.json +++ b/options/locale_next/locale_uk-UA.json @@ -105,11 +105,5 @@ "settings.visibility.description": "Видимість профілю впливає на можливість інших користувачів отримати доступ до ваших неприватних репозиторіїв. Дізнатися більше", "avatar.constraints_hint": "Розмір користувацького аватара не може перевищувати %[1]s або бути більшим за %[2]d×%[3]d пікселів", "repo.diff.commit.next-short": "Наступний", - "repo.diff.commit.previous-short": "Попередній", - "keys.ssh.link": "Ключі SSH", - "keys.gpg.link": "Ключі GPG", - "profile.edit.link": "Редагувати профіль", - "feed.atom.link": "Стрічка Atom", - "profile.actions.tooltip": "Більше дій", - "og.repo.summary_card.alt_description": "Підсумкова картка репозиторію %[1]s з описом: %[2]s" + "repo.diff.commit.previous-short": "Попередній" } diff --git a/options/locale_next/locale_zh-CN.json b/options/locale_next/locale_zh-CN.json index 62277acb95..e7c1bad81e 100644 --- a/options/locale_next/locale_zh-CN.json +++ b/options/locale_next/locale_zh-CN.json @@ -71,13 +71,5 @@ "editor.textarea.shift_tab_hint": "此行无缩进。再次按 Shift + Tab 或按 Escape 退出编辑器。", "admin.dashboard.cleanup_offline_runners": "清理离线运行器", "settings.visibility.description": "个人资料可见性设置会影响他人对您的非私有仓库的访问。了解更多", - "avatar.constraints_hint": "自定义头像大小不得超过 %[1]s,或大于 %[2]d×%[3]d 像素", - "keys.ssh.link": "SSH 密钥", - "keys.gpg.link": "GPG 密钥", - "profile.actions.tooltip": "更多操作", - "repo.diff.commit.next-short": "下个", - "repo.diff.commit.previous-short": "上个", - "feed.atom.link": "Atom 订阅源", - "profile.edit.link": "编辑个人资料", - "og.repo.summary_card.alt_description": "仓库 %[1]s 的摘要卡片,描述为:%[2]s" + "avatar.constraints_hint": "自定义头像大小不得超过 %[1]s,或大于 %[2]d×%[3]d 像素" } diff --git a/options/locale_next/locale_zh-TW.json b/options/locale_next/locale_zh-TW.json index 3ae0b00d2b..5e3e43f66e 100644 --- a/options/locale_next/locale_zh-TW.json +++ b/options/locale_next/locale_zh-TW.json @@ -68,10 +68,5 @@ "moderation.report_abuse_form.details": "這個表單是用來檢舉用戶建立垃圾帳號、儲存庫、問題、留言,或其他不當行為。", "moderation.report_abuse_form.invalid": "無效參數", "moderation.report_abuse_form.already_reported": "您已檢舉此內容", - "meta.last_line": "Rubi-chan? Hai! Nani ga suki? Choko minto yori mo a・na・ta♡ Ayumu-chan? Hai! Nani ga suki? Sutoroberii fureibaa yori mo a・na・ta♡ Shiki-chan! Hai! Nani ga suki? Kukkii and kuriimu yori mo a・na・ta♡ Minna? Hai! Nani ga suki? Mochiron daisuki AiScReam.", - "admin.dashboard.cleanup_offline_runners": "清理離線 runners", - "settings.visibility.description": "個人資料的可見度會影響他人存取您非私人儲存庫的能力。了解更多", - "avatar.constraints_hint": "自定義大頭貼的大小不得超過 %[1]s,且解析度不得大於 %[2]d×%[3]d 像素", - "repo.diff.commit.next-short": "下一個", - "repo.diff.commit.previous-short": "上一個" + "meta.last_line": "Rubi-chan? Hai! Nani ga suki? Choko minto yori mo a・na・ta♡ Ayumu-chan? Hai! Nani ga suki? Sutoroberii fureibaa yori mo a・na・ta♡ Shiki-chan! Hai! Nani ga suki? Kukkii and kuriimu yori mo a・na・ta♡ Minna? Hai! Nani ga suki? Mochiron daisuki AiScReam." } diff --git a/package-lock.json b/package-lock.json index 4555b299bf..9de06a8055 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,11 +28,11 @@ "esbuild-loader": "4.3.0", "escape-goat": "4.0.0", "fast-glob": "3.3.3", - "htmx.org": "2.0.6", + "htmx.org": "1.9.12", "idiomorph": "0.3.0", "jquery": "3.7.1", "katex": "0.16.22", - "mermaid": "11.7.0", + "mermaid": "11.6.0", "mini-css-extract-plugin": "2.9.2", "minimatch": "10.0.3", "monaco-editor": "0.52.2", @@ -63,44 +63,44 @@ "devDependencies": { "@axe-core/playwright": "4.10.2", "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.53.2", + "@playwright/test": "1.52.0", "@stoplight/spectral-cli": "6.15.0", - "@stylistic/eslint-plugin": "5.0.0", - "@stylistic/stylelint-plugin": "3.1.3", - "@vitejs/plugin-vue": "6.0.0", - "@vitest/coverage-v8": "3.2.4", + "@stylistic/eslint-plugin": "4.4.1", + "@stylistic/stylelint-plugin": "3.1.2", + "@vitejs/plugin-vue": "5.2.4", + "@vitest/coverage-v8": "3.2.3", "@vitest/eslint-plugin": "1.2.2", "@vue/test-utils": "2.4.6", - "eslint": "9.30.0", - "eslint-import-resolver-typescript": "4.4.4", + "eslint": "9.28.0", + "eslint-import-resolver-typescript": "4.4.3", "eslint-plugin-array-func": "5.0.2", - "eslint-plugin-import-x": "4.16.1", + "eslint-plugin-import-x": "4.15.1", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.7.2", "eslint-plugin-playwright": "2.2.0", "eslint-plugin-regexp": "2.9.0", - "eslint-plugin-sonarjs": "3.0.4", + "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-toml": "0.12.0", "eslint-plugin-unicorn": "59.0.1", "eslint-plugin-vitest-globals": "1.5.0", "eslint-plugin-vue": "10.2.0", "eslint-plugin-vue-scoped-css": "2.10.0", "eslint-plugin-wc": "3.0.1", - "globals": "16.3.0", - "happy-dom": "18.0.1", + "globals": "16.1.0", + "happy-dom": "18.0.0", "license-checker-rseidelsohn": "4.4.2", "markdownlint-cli": "0.45.0", "postcss-html": "1.8.0", "sharp": "0.34.2", - "stylelint": "16.21.0", + "stylelint": "16.20.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", "stylelint-value-no-unknown-custom-properties": "6.0.1", - "svgo": "4.0.0", + "svgo": "3.2.0", "typescript": "5.8.3", - "typescript-eslint": "8.35.0", + "typescript-eslint": "8.34.0", "vite-string-plugin": "1.3.4", - "vitest": "3.2.4" + "vitest": "3.2.3" }, "engines": { "node": ">= 20.0.0" @@ -216,12 +216,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", - "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.27.7" + "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -240,9 +240,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", - "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -1021,9 +1021,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", + "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1049,9 +1049,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", + "integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1146,9 +1146,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.30.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.30.0.tgz", - "integrity": "sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", + "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", "dev": true, "license": "MIT", "engines": { @@ -1169,13 +1169,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz", - "integrity": "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", + "integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.1", + "@eslint/core": "^0.15.0", "levn": "^0.4.1" }, "engines": { @@ -1183,9 +1183,9 @@ } }, "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz", + "integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1884,13 +1884,17 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.9.tgz", - "integrity": "sha512-xpz6C/vXOegF9VEtlMBlkNNIjHrLhKaFBsO4lmQGr00x5BHp7p+oliR6i7LwIcM5cZU2VjLSwm2R+/zj5IjPWg==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -1902,10 +1906,19 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/source-map": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.7.tgz", - "integrity": "sha512-maArE+jvYbj06DXh2iFlXSSDjTWXODlPTQHdDRQdGoYw7KvT4SfYCnPHfCyww8Z3JqFsW0BBjPLj8A2fwAvv7Q==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -1913,15 +1926,15 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.1.tgz", - "integrity": "sha512-mBLKRHc7Ffw/hObYb9+cunuGNjshQk+vZdwZBJoqiysK/mW3Jq0UXosq8aIhMnLevANhR9yoYfdUEOHg6M9y0g==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.26", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.26.tgz", - "integrity": "sha512-Z9rjt4BUVEbLFpw0qjCklVxxf421wrmcbP4w+LmBUxYCyJTYYSclgJD0YsCgGqQCtCIPiz7kjbYYJiAKhjJ3kA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2075,9 +2088,9 @@ } }, "node_modules/@mermaid-js/parser": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.5.0.tgz", - "integrity": "sha512-AiaN7+VjXC+3BYE+GwNezkpjIcCI2qIMB/K4S2/vMWe0q/XJCBbx5+K7iteuz7VyltX9iAK4FmVTvGc9kjOV4w==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.4.0.tgz", + "integrity": "sha512-wla8XOWvQAwuqy+gxiZqY+c7FokraOTHRWMsbB4AgRx9Sy7zKslNyejy7E+a77qHfey5GXw/ik3IXv/NHMJgaA==", "license": "MIT", "dependencies": { "langium": "3.3.1" @@ -2174,13 +2187,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.53.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.53.2.tgz", - "integrity": "sha512-tEB2U5z74ebBeyfGNZ3Jfg29AnW+5HlWhvHtb/Mqco9pFdZU1ZLNdVb2UtB5CvmiilNr2ZfVH/qMmAROG/XTzw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.52.0.tgz", + "integrity": "sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.53.2" + "playwright": "1.52.0" }, "bin": { "playwright": "cli.js" @@ -2208,13 +2221,6 @@ "object-assign": "^4.1.1" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.19", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz", - "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==", - "dev": true, - "license": "MIT" - }, "node_modules/@rollup/plugin-commonjs": { "version": "22.0.2", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz", @@ -2263,9 +2269,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", - "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz", + "integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==", "cpu": [ "arm" ], @@ -2277,9 +2283,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", - "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz", + "integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==", "cpu": [ "arm64" ], @@ -2291,9 +2297,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", - "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz", + "integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==", "cpu": [ "arm64" ], @@ -2305,9 +2311,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", - "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz", + "integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==", "cpu": [ "x64" ], @@ -2319,9 +2325,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", - "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz", + "integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==", "cpu": [ "arm64" ], @@ -2333,9 +2339,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", - "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz", + "integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==", "cpu": [ "x64" ], @@ -2347,9 +2353,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", - "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz", + "integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==", "cpu": [ "arm" ], @@ -2361,9 +2367,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", - "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz", + "integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==", "cpu": [ "arm" ], @@ -2375,9 +2381,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", - "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz", + "integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==", "cpu": [ "arm64" ], @@ -2389,9 +2395,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", - "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz", + "integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==", "cpu": [ "arm64" ], @@ -2403,9 +2409,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", - "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz", + "integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==", "cpu": [ "loong64" ], @@ -2417,9 +2423,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", - "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz", + "integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==", "cpu": [ "ppc64" ], @@ -2431,9 +2437,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", - "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz", + "integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==", "cpu": [ "riscv64" ], @@ -2445,9 +2451,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", - "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz", + "integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==", "cpu": [ "riscv64" ], @@ -2459,9 +2465,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", - "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz", + "integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==", "cpu": [ "s390x" ], @@ -2473,9 +2479,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", - "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz", + "integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==", "cpu": [ "x64" ], @@ -2487,9 +2493,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", - "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz", + "integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==", "cpu": [ "x64" ], @@ -2501,9 +2507,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", - "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz", + "integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==", "cpu": [ "arm64" ], @@ -2515,9 +2521,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", - "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz", + "integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==", "cpu": [ "ia32" ], @@ -2529,9 +2535,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", - "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz", + "integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==", "cpu": [ "x64" ], @@ -3050,16 +3056,15 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.0.0.tgz", - "integrity": "sha512-nVV2FSzeTJ3oFKw+3t9gQYQcrgbopgCASSY27QOtkhEGgSfdQQjDmzZd41NeT1myQ8Wc6l+pZllST9qIu4NKzg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.4.1.tgz", + "integrity": "sha512-CEigAk7eOLyHvdgmpZsKFwtiqS2wFwI1fn4j09IU9GmD4euFM4jEBAViWeCqaNLlbX2k2+A/Fq9cje4HQBXuJQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/types": "^8.34.1", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", + "@typescript-eslint/utils": "^8.32.1", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "estraverse": "^5.3.0", "picomatch": "^4.0.2" }, @@ -3084,9 +3089,9 @@ } }, "node_modules/@stylistic/stylelint-plugin": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.1.3.tgz", - "integrity": "sha512-85fsmzgsIVmyG3/GFrjuYj6Cz8rAM7IZiPiXCMiSMfoDOC1lOrzrXPDk24WqviAghnPqGpx8b0caK2PuewWGFg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.1.2.tgz", + "integrity": "sha512-tylFJGMQo62alGazK74MNxFjMagYOHmBZiePZFOJK2n13JZta0uVkB3Bh5qodUmOLtRH+uxH297EibK14UKm8g==", "dev": true, "license": "MIT", "dependencies": { @@ -3094,10 +3099,10 @@ "@csstools/css-tokenizer": "^3.0.1", "@csstools/media-query-list-parser": "^3.0.1", "is-plain-object": "^5.0.0", - "postcss": "^8.4.41", "postcss-selector-parser": "^6.1.2", "postcss-value-parser": "^4.2.0", - "style-search": "^0.1.0" + "style-search": "^0.1.0", + "stylelint": "^16.8.2" }, "engines": { "node": "^18.12 || >=20.9" @@ -3112,6 +3117,16 @@ "integrity": "sha512-wpCQMhf5p5GhNg2MmGKXzUNwxe7zRiCsmqYsamez2beP7mKPCSiu+BjZcdN95yYSzO857kr0VfQewmGpS77nqA==", "license": "MIT" }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", @@ -3494,9 +3509,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.2.tgz", - "integrity": "sha512-9pLGGwdzOUBDYi0GNjM97FIA+f92fqSke6joWeBjWXllfNxZBs7qeMF7tvtOIsbY45xkWkxrdwUfUf3MnQa9gA==", + "version": "20.19.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.0.tgz", + "integrity": "sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -3546,17 +3561,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz", - "integrity": "sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", + "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.35.0", - "@typescript-eslint/type-utils": "8.35.0", - "@typescript-eslint/utils": "8.35.0", - "@typescript-eslint/visitor-keys": "8.35.0", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/type-utils": "8.34.0", + "@typescript-eslint/utils": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -3570,7 +3585,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.35.0", + "@typescript-eslint/parser": "^8.34.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -3586,16 +3601,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.0.tgz", - "integrity": "sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", + "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.35.0", - "@typescript-eslint/types": "8.35.0", - "@typescript-eslint/typescript-estree": "8.35.0", - "@typescript-eslint/visitor-keys": "8.35.0", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4" }, "engines": { @@ -3611,14 +3626,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.0.tgz", - "integrity": "sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", + "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.35.0", - "@typescript-eslint/types": "^8.35.0", + "@typescript-eslint/tsconfig-utils": "^8.34.0", + "@typescript-eslint/types": "^8.34.0", "debug": "^4.3.4" }, "engines": { @@ -3633,14 +3648,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz", - "integrity": "sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", + "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.0", - "@typescript-eslint/visitor-keys": "8.35.0" + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3651,9 +3666,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz", - "integrity": "sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", + "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", "dev": true, "license": "MIT", "engines": { @@ -3668,14 +3683,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz", - "integrity": "sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", + "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.35.0", - "@typescript-eslint/utils": "8.35.0", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/utils": "8.34.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3692,9 +3707,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.0.tgz", - "integrity": "sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", + "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", "dev": true, "license": "MIT", "engines": { @@ -3706,16 +3721,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz", - "integrity": "sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", + "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.35.0", - "@typescript-eslint/tsconfig-utils": "8.35.0", - "@typescript-eslint/types": "8.35.0", - "@typescript-eslint/visitor-keys": "8.35.0", + "@typescript-eslint/project-service": "8.34.0", + "@typescript-eslint/tsconfig-utils": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3768,16 +3783,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.0.tgz", - "integrity": "sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", + "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.35.0", - "@typescript-eslint/types": "8.35.0", - "@typescript-eslint/typescript-estree": "8.35.0" + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3792,14 +3807,14 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz", - "integrity": "sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", + "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.0", - "eslint-visitor-keys": "^4.2.1" + "@typescript-eslint/types": "8.34.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3810,9 +3825,9 @@ } }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.2.tgz", - "integrity": "sha512-tS+lqTU3N0kkthU+rYp0spAYq15DU8ld9kXkaKg9sbQqJNF+WPMuNHZQGCgdxrUOEO0j22RKMwRVhF1HTl+X8A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.0.tgz", + "integrity": "sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==", "cpu": [ "arm" ], @@ -3824,9 +3839,9 @@ ] }, "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.2.tgz", - "integrity": "sha512-MffGiZULa/KmkNjHeuuflLVqfhqLv1vZLm8lWIyeADvlElJ/GLSOkoUX+5jf4/EGtfwrNFcEaB8BRas03KT0/Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.0.tgz", + "integrity": "sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==", "cpu": [ "arm64" ], @@ -3838,9 +3853,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.2.tgz", - "integrity": "sha512-dzJYK5rohS1sYl1DHdJ3mwfwClJj5BClQnQSyAgEfggbUwA9RlROQSSbKBLqrGfsiC/VyrDPtbO8hh56fnkbsQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.0.tgz", + "integrity": "sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==", "cpu": [ "arm64" ], @@ -3852,9 +3867,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.2.tgz", - "integrity": "sha512-gaIMWK+CWtXcg9gUyznkdV54LzQ90S3X3dn8zlh+QR5Xy7Y+Efqw4Rs4im61K1juy4YNb67vmJsCDAGOnIeffQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.0.tgz", + "integrity": "sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==", "cpu": [ "x64" ], @@ -3866,9 +3881,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.2.tgz", - "integrity": "sha512-S7QpkMbVoVJb0xwHFwujnwCAEDe/596xqY603rpi/ioTn9VDgBHnCCxh+UFrr5yxuMH+dliHfjwCZJXOPJGPnw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.0.tgz", + "integrity": "sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==", "cpu": [ "x64" ], @@ -3880,9 +3895,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.2.tgz", - "integrity": "sha512-+XPUMCuCCI80I46nCDFbGum0ZODP5NWGiwS3Pj8fOgsG5/ctz+/zzuBlq/WmGa+EjWZdue6CF0aWWNv84sE1uw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.0.tgz", + "integrity": "sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==", "cpu": [ "arm" ], @@ -3894,9 +3909,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.2.tgz", - "integrity": "sha512-sqvUyAd1JUpwbz33Ce2tuTLJKM+ucSsYpPGl2vuFwZnEIg0CmdxiZ01MHQ3j6ExuRqEDUCy8yvkDKvjYFPb8Zg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.0.tgz", + "integrity": "sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==", "cpu": [ "arm" ], @@ -3908,9 +3923,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.2.tgz", - "integrity": "sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.0.tgz", + "integrity": "sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==", "cpu": [ "arm64" ], @@ -3922,9 +3937,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.2.tgz", - "integrity": "sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.0.tgz", + "integrity": "sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==", "cpu": [ "arm64" ], @@ -3936,9 +3951,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.2.tgz", - "integrity": "sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.0.tgz", + "integrity": "sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==", "cpu": [ "ppc64" ], @@ -3950,9 +3965,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.2.tgz", - "integrity": "sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.0.tgz", + "integrity": "sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==", "cpu": [ "riscv64" ], @@ -3964,9 +3979,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.2.tgz", - "integrity": "sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.0.tgz", + "integrity": "sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==", "cpu": [ "riscv64" ], @@ -3978,9 +3993,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.2.tgz", - "integrity": "sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.0.tgz", + "integrity": "sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==", "cpu": [ "s390x" ], @@ -3992,9 +4007,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.2.tgz", - "integrity": "sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.0.tgz", + "integrity": "sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==", "cpu": [ "x64" ], @@ -4006,9 +4021,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.2.tgz", - "integrity": "sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.0.tgz", + "integrity": "sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==", "cpu": [ "x64" ], @@ -4020,9 +4035,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.2.tgz", - "integrity": "sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.0.tgz", + "integrity": "sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==", "cpu": [ "wasm32" ], @@ -4037,9 +4052,9 @@ } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.2.tgz", - "integrity": "sha512-EdFbGn7o1SxGmN6aZw9wAkehZJetFPao0VGZ9OMBwKx6TkvDuj6cNeLimF/Psi6ts9lMOe+Dt6z19fZQ9Ye2fw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.0.tgz", + "integrity": "sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==", "cpu": [ "arm64" ], @@ -4051,9 +4066,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.2.tgz", - "integrity": "sha512-JY9hi1p7AG+5c/dMU8o2kWemM8I6VZxfGwn1GCtf3c5i+IKcMo2NQ8OjZ4Z3/itvY/Si3K10jOBQn7qsD/whUA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.0.tgz", + "integrity": "sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==", "cpu": [ "ia32" ], @@ -4065,9 +4080,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.2.tgz", - "integrity": "sha512-ryoo+EB19lMxAd80ln9BVf8pdOAxLb97amrQ3SFN9OCRn/5M5wvwDgAe4i8ZjhpbiHoDeP8yavcTEnpKBo7lZg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz", + "integrity": "sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==", "cpu": [ "x64" ], @@ -4079,26 +4094,23 @@ ] }, "node_modules/@vitejs/plugin-vue": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.0.tgz", - "integrity": "sha512-iAliE72WsdhjzTOp2DtvKThq1VBC4REhwRcaA+zPAAph6I+OQhUXv+Xu2KS7ElxYtb7Zc/3R30Hwv1DxEo7NXQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", "dev": true, "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.19" - }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "node_modules/@vitest/coverage-v8": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", - "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.3.tgz", + "integrity": "sha512-D1QKzngg8PcDoCE8FHSZhREDuEy+zcKmMiMafYse41RZpBE5EDJyKOTdqK3RQfsV2S2nyKor5KCs8PyPRFqKPg==", "dev": true, "license": "MIT", "dependencies": { @@ -4120,8 +4132,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.2.4", - "vitest": "3.2.4" + "@vitest/browser": "3.2.3", + "vitest": "3.2.3" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -4163,15 +4175,15 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", - "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.3.tgz", + "integrity": "sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -4180,13 +4192,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.3.tgz", + "integrity": "sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.4", + "@vitest/spy": "3.2.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -4234,9 +4246,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", - "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.3.tgz", + "integrity": "sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==", "dev": true, "license": "MIT", "dependencies": { @@ -4247,13 +4259,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", - "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.3.tgz", + "integrity": "sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.4", + "@vitest/utils": "3.2.3", "pathe": "^2.0.3", "strip-literal": "^3.0.0" }, @@ -4262,13 +4274,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", - "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.3.tgz", + "integrity": "sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", + "@vitest/pretty-format": "3.2.3", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -4287,9 +4299,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", - "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.3.tgz", + "integrity": "sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==", "dev": true, "license": "MIT", "dependencies": { @@ -4300,14 +4312,14 @@ } }, "node_modules/@vitest/utils": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", - "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.3.tgz", + "integrity": "sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.4", - "loupe": "^3.1.4", + "@vitest/pretty-format": "3.2.3", + "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, "funding": { @@ -5143,9 +5155,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "funding": [ { "type": "opencollective", @@ -5162,8 +5174,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -5334,9 +5346,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001726", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", - "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", + "version": "1.0.30001723", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", + "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", "funding": [ { "type": "opencollective", @@ -5882,9 +5894,9 @@ } }, "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5913,9 +5925,9 @@ } }, "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -6904,9 +6916,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.177", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", - "integrity": "sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==", + "version": "1.5.167", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.167.tgz", + "integrity": "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -6925,9 +6937,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -7250,19 +7262,19 @@ } }, "node_modules/eslint": { - "version": "9.30.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.30.0.tgz", - "integrity": "sha512-iN/SiPxmQu6EVkf+m1qpBxzUhE12YqFLOSySuOyVLJLEF9nzTf+h/1AJYc1JWzCnktggeNrjvQGLngDzXirU6g==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", + "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.30.0", + "@eslint/js": "9.28.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -7274,9 +7286,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -7327,14 +7339,14 @@ } }, "node_modules/eslint-import-context": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", - "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.8.tgz", + "integrity": "sha512-bq+F7nyc65sKpZGT09dY0S0QrOnQtuDVIfyTGQ8uuvtMIF7oHp6CEP3mouN0rrnYF3Jqo6Ke0BfU/5wASZue1w==", "dev": true, "license": "MIT", "dependencies": { "get-tsconfig": "^4.10.1", - "stable-hash-x": "^0.2.0" + "stable-hash-x": "^0.1.1" }, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" @@ -7352,9 +7364,9 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.4.tgz", - "integrity": "sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.3.tgz", + "integrity": "sha512-elVDn1eWKFrWlzxlWl9xMt8LltjKl161Ix50JFC50tHXI5/TRP32SNEqlJ/bo/HV+g7Rou/tlPQU2AcRtIhrOg==", "dev": true, "license": "ISC", "dependencies": { @@ -7362,7 +7374,7 @@ "eslint-import-context": "^0.1.8", "get-tsconfig": "^4.10.1", "is-bun-module": "^2.0.0", - "stable-hash-x": "^0.2.0", + "stable-hash-x": "^0.1.1", "tinyglobby": "^0.2.14", "unrs-resolver": "^1.7.11" }, @@ -7400,21 +7412,21 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.16.1.tgz", - "integrity": "sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.15.1.tgz", + "integrity": "sha512-JfVpNg1qMkPD66iaSgmMoSYeUCGS8UFSm3GwHV0IbuV3Knar/SyK5qqCct9+AxoMIzaM+KSO7KK5pOeOkC/3GQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.35.0", + "@typescript-eslint/types": "^8.33.1", "comment-parser": "^1.4.1", "debug": "^4.4.1", - "eslint-import-context": "^0.1.9", + "eslint-import-context": "^0.1.7", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", "semver": "^7.7.2", - "stable-hash-x": "^0.2.0", - "unrs-resolver": "^1.9.2" + "stable-hash-x": "^0.1.1", + "unrs-resolver": "^1.7.10" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7523,9 +7535,9 @@ } }, "node_modules/eslint-plugin-sonarjs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-3.0.4.tgz", - "integrity": "sha512-ftQcP811kRJNXapqpQXHErEoVOdTPfYPPYd7n3AExIPwv4qWKKHf4slFvXmodiOnfgy1Tl3waPZZLD7lcvJOtw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-3.0.2.tgz", + "integrity": "sha512-LxjbfwI7ypENeTmGyKmDyNux3COSkMi7H/6Cal5StSLQ6edf0naP45SZR43OclaNR7WfhVTZdhOn63q3/Y6puQ==", "dev": true, "license": "LGPL-3.0-only", "dependencies": { @@ -7534,11 +7546,10 @@ "bytes": "3.1.2", "functional-red-black-tree": "1.0.1", "jsx-ast-utils": "3.3.5", - "lodash.merge": "4.6.2", "minimatch": "9.0.5", "scslre": "0.3.0", - "semver": "7.7.2", - "typescript": ">=5" + "semver": "7.7.1", + "typescript": "^5" }, "peerDependencies": { "eslint": "^8.0.0 || ^9.0.0" @@ -7577,6 +7588,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/eslint-plugin-sonarjs/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-plugin-toml": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/eslint-plugin-toml/-/eslint-plugin-toml-0.12.0.tgz", @@ -7903,9 +7927,9 @@ } }, "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", + "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", "license": "MIT" }, "node_modules/fast-deep-equal": { @@ -8440,9 +8464,9 @@ } }, "node_modules/globals": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", - "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", + "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", "dev": true, "license": "MIT", "engines": { @@ -8539,9 +8563,9 @@ } }, "node_modules/happy-dom": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-18.0.1.tgz", - "integrity": "sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-18.0.0.tgz", + "integrity": "sha512-o3p2Axi1EdIfMaOUulDzO/5yXzLLV0g/54eLPVrkt3u20r3yOuOenHpyp2clAJ0eHMc+HyE139ulQxl+8pEJIw==", "dev": true, "license": "MIT", "dependencies": { @@ -8652,9 +8676,9 @@ } }, "node_modules/hookified": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.10.0.tgz", - "integrity": "sha512-dJw0492Iddsj56U1JsSTm9E/0B/29a1AuoSLRAte8vQg/kaTGF3IgjEWT8c8yG4cC10+HisE1x5QAwR0Xwc+DA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.9.1.tgz", + "integrity": "sha512-u3pxtGhKjcSXnGm1CX6aXS9xew535j3lkOCegbA6jdyh0BaAjTbXI4aslKstCr6zUNtoCxFGFKwjbSHdGrMB8g==", "dev": true, "license": "MIT" }, @@ -8722,9 +8746,9 @@ } }, "node_modules/htmx.org": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-2.0.6.tgz", - "integrity": "sha512-7ythjYneGSk3yCHgtCnQeaoF+D+o7U2LF37WU3O0JYv3gTZSicdEFiI/Ai/NJyC5ZpYJWMpUb11OC5Lr6AfAqA==", + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/htmx.org/-/htmx.org-1.9.12.tgz", + "integrity": "sha512-VZAohXyF7xPGS52IM8d1T1283y+X4D+Owf3qY1NZ9RuBypyu9l8cGsxUMAG5fEAb/DhT7rDoJ9Hpu5/HxFD3cw==", "license": "0BSD" }, "node_modules/iconv-lite": { @@ -9969,9 +9993,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.37.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", - "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz", + "integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==", "dev": true, "license": "MIT" }, @@ -10227,9 +10251,9 @@ "license": "MIT" }, "node_modules/loupe": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", - "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", "dev": true, "license": "MIT" }, @@ -10538,14 +10562,14 @@ } }, "node_modules/mermaid": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.7.0.tgz", - "integrity": "sha512-/1/5R0rt0Z1Ak0CuznAnCF3HtQgayRXUz6SguzOwN4L+DuCobz0UxnQ+ZdTSZ3AugKVVh78tiVmsHpHWV25TCw==", + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.6.0.tgz", + "integrity": "sha512-PE8hGUy1LDlWIHWBP05SFdqUHGmRcCcK4IzpOKPE35eOw+G9zZgcnMpyunJVUEOgb//KBORPjysKndw8bFLuRg==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.0.4", "@iconify/utils": "^2.1.33", - "@mermaid-js/parser": "^0.5.0", + "@mermaid-js/parser": "^0.4.0", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", @@ -10554,7 +10578,7 @@ "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.11", "dayjs": "^1.11.13", - "dompurify": "^3.2.5", + "dompurify": "^3.2.4", "katex": "^0.16.9", "khroma": "^2.1.0", "lodash-es": "^4.17.21", @@ -11320,9 +11344,9 @@ } }, "node_modules/napi-postinstall": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.5.tgz", - "integrity": "sha512-kmsgUvCRIJohHjbZ3V8avP0I1Pekw329MVAMDzVxsrkjgdnqiwvMX5XwR+hWV66vsAtZ+iM+fVnq8RTQawUmCQ==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz", + "integrity": "sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==", "dev": true, "license": "MIT", "bin": { @@ -11803,9 +11827,9 @@ "license": "MIT" }, "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, "license": "MIT", "engines": { @@ -11919,24 +11943,24 @@ } }, "node_modules/pkg-types": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.1.tgz", - "integrity": "sha512-eY0QFb6eSwc9+0d/5D2lFFUq+A3n3QNGSy/X2Nvp+6MfzGw2u6EbA7S80actgjY1lkvvI0pqB+a4hioMh443Ew==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", + "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==", "license": "MIT", "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", + "confbox": "^0.2.1", + "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "node_modules/playwright": { - "version": "1.53.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.2.tgz", - "integrity": "sha512-6K/qQxVFuVQhRQhFsVZ9fGeatxirtrpPgxzBYWyZLEXJzqYwuL4fuNmfOfD5et1tJE4GScKyPNeLhZeRwuTU3A==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", + "integrity": "sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.53.2" + "playwright-core": "1.52.0" }, "bin": { "playwright": "cli.js" @@ -11949,9 +11973,9 @@ } }, "node_modules/playwright-core": { - "version": "1.53.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.53.2.tgz", - "integrity": "sha512-ox/OytMy+2w1jcYEYlOo1Hhp8hZkLCximMTUTMBXjGUA1KoFfiSZ+DU+3a739jsPY0yoKH2TFy9S2fsJas8yAw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.52.0.tgz", + "integrity": "sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -13566,9 +13590,9 @@ } }, "node_modules/stable-hash-x": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", - "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.1.1.tgz", + "integrity": "sha512-l0x1D6vhnsNUGPFVDx45eif0y6eedVC8nm5uACTrVFJFtl2mLRW17aWtVyxFCpn5t94VUPkjU8vSLwIuwwqtJQ==", "dev": true, "license": "MIT", "engines": { @@ -13777,9 +13801,9 @@ "license": "ISC" }, "node_modules/stylelint": { - "version": "16.21.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.21.0.tgz", - "integrity": "sha512-ki3PpJGG7xhm3WtINoWGnlvqAmbqSexoRMbEMJzlwewSIOqPRKPlq452c22xAdEJISVi80r+I7KL9GPUiwFgbg==", + "version": "16.20.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.20.0.tgz", + "integrity": "sha512-B5Myu9WRxrgKuLs3YyUXLP2H0mrbejwNxPmyADlACWwFsrL8Bmor/nTSh4OMae5sHjOz6gkSeccQH34gM4/nAw==", "dev": true, "funding": [ { @@ -13793,9 +13817,9 @@ ], "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4", - "@csstools/media-query-list-parser": "^4.0.3", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "@csstools/media-query-list-parser": "^4.0.2", "@csstools/selector-specificity": "^5.0.0", "@dual-bundle/import-meta-resolve": "^4.1.0", "balanced-match": "^2.0.0", @@ -13806,21 +13830,21 @@ "debug": "^4.4.1", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.1.1", + "file-entry-cache": "^10.1.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", "html-tags": "^3.3.1", - "ignore": "^7.0.5", + "ignore": "^7.0.4", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.37.0", + "known-css-properties": "^0.36.0", "mathml-tag-names": "^2.1.3", "meow": "^13.2.0", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "picocolors": "^1.1.1", - "postcss": "^8.5.5", + "postcss": "^8.5.3", "postcss-resolve-nested-selector": "^0.1.6", "postcss-safe-parser": "^7.0.1", "postcss-selector-parser": "^7.1.0", @@ -14178,25 +14202,25 @@ "dev": true }, "node_modules/svgo": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", - "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", + "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", "dev": true, "license": "MIT", "dependencies": { - "commander": "^11.1.0", + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", "css-select": "^5.1.0", - "css-tree": "^3.0.1", + "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", - "picocolors": "^1.1.1", - "sax": "^1.4.1" + "picocolors": "^1.0.0" }, "bin": { - "svgo": "bin/svgo.js" + "svgo": "bin/svgo" }, "engines": { - "node": ">=16" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", @@ -14204,21 +14228,35 @@ } }, "node_modules/svgo/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">= 10" } }, - "node_modules/svgo/node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "node_modules/svgo/node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/svgo/node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true, + "license": "CC0-1.0" }, "node_modules/swagger-ui-dist": { "version": "5.17.14", @@ -14338,9 +14376,9 @@ } }, "node_modules/terser": { - "version": "5.43.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.42.0.tgz", + "integrity": "sha512-UYCvU9YQW2f/Vwl+P0GfhxJxbUGLwd+5QrrGgLajzWAtC/23AX0vcise32kkP7Eu0Wu9VlzzHAXkLObgjQfFlQ==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -14573,9 +14611,9 @@ } }, "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", + "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", "dev": true, "license": "MIT", "engines": { @@ -14834,15 +14872,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.35.0.tgz", - "integrity": "sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.34.0.tgz", + "integrity": "sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.35.0", - "@typescript-eslint/parser": "8.35.0", - "@typescript-eslint/utils": "8.35.0" + "@typescript-eslint/eslint-plugin": "8.34.0", + "@typescript-eslint/parser": "8.34.0", + "@typescript-eslint/utils": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -14917,38 +14955,38 @@ } }, "node_modules/unrs-resolver": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.2.tgz", - "integrity": "sha512-VUyWiTNQD7itdiMuJy+EuLEErLj3uwX/EpHQF8EOf33Dq3Ju6VW1GXm+swk6+1h7a49uv9fKZ+dft9jU7esdLA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.0.tgz", + "integrity": "sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "napi-postinstall": "^0.2.4" + "napi-postinstall": "^0.2.2" }, "funding": { "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.9.2", - "@unrs/resolver-binding-android-arm64": "1.9.2", - "@unrs/resolver-binding-darwin-arm64": "1.9.2", - "@unrs/resolver-binding-darwin-x64": "1.9.2", - "@unrs/resolver-binding-freebsd-x64": "1.9.2", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.2", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.2", - "@unrs/resolver-binding-linux-arm64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-arm64-musl": "1.9.2", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-riscv64-musl": "1.9.2", - "@unrs/resolver-binding-linux-s390x-gnu": "1.9.2", - "@unrs/resolver-binding-linux-x64-gnu": "1.9.2", - "@unrs/resolver-binding-linux-x64-musl": "1.9.2", - "@unrs/resolver-binding-wasm32-wasi": "1.9.2", - "@unrs/resolver-binding-win32-arm64-msvc": "1.9.2", - "@unrs/resolver-binding-win32-ia32-msvc": "1.9.2", - "@unrs/resolver-binding-win32-x64-msvc": "1.9.2" + "@unrs/resolver-binding-android-arm-eabi": "1.9.0", + "@unrs/resolver-binding-android-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-x64": "1.9.0", + "@unrs/resolver-binding-freebsd-x64": "1.9.0", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-arm64-musl": "1.9.0", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-musl": "1.9.0", + "@unrs/resolver-binding-linux-s390x-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-musl": "1.9.0", + "@unrs/resolver-binding-wasm32-wasi": "1.9.0", + "@unrs/resolver-binding-win32-arm64-msvc": "1.9.0", + "@unrs/resolver-binding-win32-ia32-msvc": "1.9.0", + "@unrs/resolver-binding-win32-x64-msvc": "1.9.0" } }, "node_modules/update-browserslist-db": { @@ -15055,24 +15093,24 @@ "license": "MIT" }, "node_modules/vite": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.0.tgz", - "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.6", + "fdir": "^6.4.4", "picomatch": "^4.0.2", - "postcss": "^8.5.6", - "rollup": "^4.40.0", - "tinyglobby": "^0.2.14" + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -15081,14 +15119,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", - "less": "^4.0.0", + "less": "*", "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -15130,9 +15168,9 @@ } }, "node_modules/vite-node": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", - "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.3.tgz", + "integrity": "sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==", "dev": true, "license": "MIT", "dependencies": { @@ -15160,9 +15198,9 @@ "license": "BSD-2-Clause" }, "node_modules/vite/node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true, "license": "MIT" }, @@ -15209,43 +15247,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vite/node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/vite/node_modules/rollup": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", - "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz", + "integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -15255,44 +15264,44 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.1", - "@rollup/rollup-android-arm64": "4.44.1", - "@rollup/rollup-darwin-arm64": "4.44.1", - "@rollup/rollup-darwin-x64": "4.44.1", - "@rollup/rollup-freebsd-arm64": "4.44.1", - "@rollup/rollup-freebsd-x64": "4.44.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", - "@rollup/rollup-linux-arm-musleabihf": "4.44.1", - "@rollup/rollup-linux-arm64-gnu": "4.44.1", - "@rollup/rollup-linux-arm64-musl": "4.44.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-musl": "4.44.1", - "@rollup/rollup-linux-s390x-gnu": "4.44.1", - "@rollup/rollup-linux-x64-gnu": "4.44.1", - "@rollup/rollup-linux-x64-musl": "4.44.1", - "@rollup/rollup-win32-arm64-msvc": "4.44.1", - "@rollup/rollup-win32-ia32-msvc": "4.44.1", - "@rollup/rollup-win32-x64-msvc": "4.44.1", + "@rollup/rollup-android-arm-eabi": "4.43.0", + "@rollup/rollup-android-arm64": "4.43.0", + "@rollup/rollup-darwin-arm64": "4.43.0", + "@rollup/rollup-darwin-x64": "4.43.0", + "@rollup/rollup-freebsd-arm64": "4.43.0", + "@rollup/rollup-freebsd-x64": "4.43.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.43.0", + "@rollup/rollup-linux-arm-musleabihf": "4.43.0", + "@rollup/rollup-linux-arm64-gnu": "4.43.0", + "@rollup/rollup-linux-arm64-musl": "4.43.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.43.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-musl": "4.43.0", + "@rollup/rollup-linux-s390x-gnu": "4.43.0", + "@rollup/rollup-linux-x64-gnu": "4.43.0", + "@rollup/rollup-linux-x64-musl": "4.43.0", + "@rollup/rollup-win32-arm64-msvc": "4.43.0", + "@rollup/rollup-win32-ia32-msvc": "4.43.0", + "@rollup/rollup-win32-x64-msvc": "4.43.0", "fsevents": "~2.3.2" } }, "node_modules/vitest": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", - "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.3.tgz", + "integrity": "sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.4", - "@vitest/mocker": "3.2.4", - "@vitest/pretty-format": "^3.2.4", - "@vitest/runner": "3.2.4", - "@vitest/snapshot": "3.2.4", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", + "@vitest/expect": "3.2.3", + "@vitest/mocker": "3.2.3", + "@vitest/pretty-format": "^3.2.3", + "@vitest/runner": "3.2.3", + "@vitest/snapshot": "3.2.3", + "@vitest/spy": "3.2.3", + "@vitest/utils": "3.2.3", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -15303,10 +15312,10 @@ "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", - "tinypool": "^1.1.1", + "tinypool": "^1.1.0", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.4", + "vite-node": "3.2.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -15322,8 +15331,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.4", - "@vitest/ui": "3.2.4", + "@vitest/browser": "3.2.3", + "@vitest/ui": "3.2.3", "happy-dom": "*", "jsdom": "*" }, @@ -15469,9 +15478,9 @@ "license": "MIT" }, "node_modules/vue-eslint-parser": { - "version": "10.1.4", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.4.tgz", - "integrity": "sha512-EIZvCukIEMHEb3mxOKemtvWR1fcUAdWWAgkfyjmRHzvyhrZvBvH9oz69+thDIWhGiIQjZnPkCn8yHqvjM+a9eg==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.3.tgz", + "integrity": "sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ==", "dev": true, "license": "MIT", "peer": true, @@ -15699,9 +15708,9 @@ } }, "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.2.tgz", + "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==", "license": "MIT", "engines": { "node": ">=10.13.0" diff --git a/package.json b/package.json index 3623c143e0..f7df1b3f38 100644 --- a/package.json +++ b/package.json @@ -27,11 +27,11 @@ "esbuild-loader": "4.3.0", "escape-goat": "4.0.0", "fast-glob": "3.3.3", - "htmx.org": "2.0.6", + "htmx.org": "1.9.12", "idiomorph": "0.3.0", "jquery": "3.7.1", "katex": "0.16.22", - "mermaid": "11.7.0", + "mermaid": "11.6.0", "mini-css-extract-plugin": "2.9.2", "minimatch": "10.0.3", "monaco-editor": "0.52.2", @@ -62,44 +62,44 @@ "devDependencies": { "@axe-core/playwright": "4.10.2", "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.53.2", + "@playwright/test": "1.52.0", "@stoplight/spectral-cli": "6.15.0", - "@stylistic/eslint-plugin": "5.0.0", - "@stylistic/stylelint-plugin": "3.1.3", - "@vitejs/plugin-vue": "6.0.0", - "@vitest/coverage-v8": "3.2.4", + "@stylistic/eslint-plugin": "4.4.1", + "@stylistic/stylelint-plugin": "3.1.2", + "@vitejs/plugin-vue": "5.2.4", + "@vitest/coverage-v8": "3.2.3", "@vitest/eslint-plugin": "1.2.2", "@vue/test-utils": "2.4.6", - "eslint": "9.30.0", - "eslint-import-resolver-typescript": "4.4.4", + "eslint": "9.28.0", + "eslint-import-resolver-typescript": "4.4.3", "eslint-plugin-array-func": "5.0.2", - "eslint-plugin-import-x": "4.16.1", + "eslint-plugin-import-x": "4.15.1", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.7.2", "eslint-plugin-playwright": "2.2.0", "eslint-plugin-regexp": "2.9.0", - "eslint-plugin-sonarjs": "3.0.4", + "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-toml": "0.12.0", "eslint-plugin-unicorn": "59.0.1", "eslint-plugin-vitest-globals": "1.5.0", "eslint-plugin-vue": "10.2.0", "eslint-plugin-vue-scoped-css": "2.10.0", "eslint-plugin-wc": "3.0.1", - "globals": "16.3.0", - "happy-dom": "18.0.1", + "globals": "16.1.0", + "happy-dom": "18.0.0", "license-checker-rseidelsohn": "4.4.2", "markdownlint-cli": "0.45.0", "postcss-html": "1.8.0", "sharp": "0.34.2", - "stylelint": "16.21.0", + "stylelint": "16.20.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", "stylelint-value-no-unknown-custom-properties": "6.0.1", - "svgo": "4.0.0", + "svgo": "3.2.0", "typescript": "5.8.3", - "typescript-eslint": "8.35.0", + "typescript-eslint": "8.34.0", "vite-string-plugin": "1.3.4", - "vitest": "3.2.4" + "vitest": "3.2.3" }, "browserslist": [ "defaults" diff --git a/public/assets/img/svg/gitea-alt.svg b/public/assets/img/svg/gitea-alt.svg index efe4830a0b..53e3f17c13 100644 --- a/public/assets/img/svg/gitea-alt.svg +++ b/public/assets/img/svg/gitea-alt.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-chef.svg b/public/assets/img/svg/gitea-chef.svg index 8fd8ed325d..c5e8a721cc 100644 --- a/public/assets/img/svg/gitea-chef.svg +++ b/public/assets/img/svg/gitea-chef.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-debian.svg b/public/assets/img/svg/gitea-debian.svg index e92d0b6937..fa2f2f49dc 100644 --- a/public/assets/img/svg/gitea-debian.svg +++ b/public/assets/img/svg/gitea-debian.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-gitbucket.svg b/public/assets/img/svg/gitea-gitbucket.svg index b9e99724b2..62f603484e 100644 --- a/public/assets/img/svg/gitea-gitbucket.svg +++ b/public/assets/img/svg/gitea-gitbucket.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-gitlab.svg b/public/assets/img/svg/gitea-gitlab.svg index e2d708e7be..03fcb0b87e 100644 --- a/public/assets/img/svg/gitea-gitlab.svg +++ b/public/assets/img/svg/gitea-gitlab.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-google.svg b/public/assets/img/svg/gitea-google.svg index 26ee04cb64..7dd2622df6 100644 --- a/public/assets/img/svg/gitea-google.svg +++ b/public/assets/img/svg/gitea-google.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-maven.svg b/public/assets/img/svg/gitea-maven.svg index f6ece7dc28..320d01a234 100644 --- a/public/assets/img/svg/gitea-maven.svg +++ b/public/assets/img/svg/gitea-maven.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-microsoftonline.svg b/public/assets/img/svg/gitea-microsoftonline.svg index c143eccbb6..f2ce13ac22 100644 --- a/public/assets/img/svg/gitea-microsoftonline.svg +++ b/public/assets/img/svg/gitea-microsoftonline.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-npm.svg b/public/assets/img/svg/gitea-npm.svg index 2b05c79353..7ef74e72bd 100644 --- a/public/assets/img/svg/gitea-npm.svg +++ b/public/assets/img/svg/gitea-npm.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-onedev.svg b/public/assets/img/svg/gitea-onedev.svg index 7ecd18895d..94ad1bab31 100644 --- a/public/assets/img/svg/gitea-onedev.svg +++ b/public/assets/img/svg/gitea-onedev.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-openid.svg b/public/assets/img/svg/gitea-openid.svg index 10c37145a3..f4702d2cdf 100644 --- a/public/assets/img/svg/gitea-openid.svg +++ b/public/assets/img/svg/gitea-openid.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-rubygems.svg b/public/assets/img/svg/gitea-rubygems.svg index 7cd9d34e6a..4e43bdf2f4 100644 --- a/public/assets/img/svg/gitea-rubygems.svg +++ b/public/assets/img/svg/gitea-rubygems.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-swift.svg b/public/assets/img/svg/gitea-swift.svg index 891ac12b56..4182100185 100644 --- a/public/assets/img/svg/gitea-swift.svg +++ b/public/assets/img/svg/gitea-swift.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/gitea-vagrant.svg b/public/assets/img/svg/gitea-vagrant.svg index 18b05e900d..ba50101d52 100644 --- a/public/assets/img/svg/gitea-vagrant.svg +++ b/public/assets/img/svg/gitea-vagrant.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/release-notes-published/12.0.0.md b/release-notes-published/13.0.0.md similarity index 100% rename from release-notes-published/12.0.0.md rename to release-notes-published/13.0.0.md diff --git a/routers/api/v1/activitypub/actor.go b/routers/api/v1/activitypub/actor.go index 0ff822c7f4..e49f277842 100644 --- a/routers/api/v1/activitypub/actor.go +++ b/routers/api/v1/activitypub/actor.go @@ -32,7 +32,7 @@ func Actor(ctx *context.APIContext) { actor := ap.ActorNew(ap.IRI(link), ap.ApplicationType) actor.PreferredUsername = ap.NaturalLanguageValuesNew() - err := actor.PreferredUsername.Set("en", ap.Content("ghost")) + err := actor.PreferredUsername.Set("en", ap.Content(setting.Domain)) if err != nil { ctx.ServerError("PreferredUsername.Set", err) return @@ -41,6 +41,8 @@ func Actor(ctx *context.APIContext) { actor.URL = ap.IRI(setting.AppURL) actor.Inbox = ap.IRI(link + "/inbox") + actor.Outbox = ap.IRI(link + "/outbox") + actor.PublicKey.ID = ap.IRI(link + "#main-key") actor.PublicKey.Owner = ap.IRI(link) diff --git a/routers/api/v1/activitypub/reqsignature.go b/routers/api/v1/activitypub/reqsignature.go index 91274249ec..b84fbe05fa 100644 --- a/routers/api/v1/activitypub/reqsignature.go +++ b/routers/api/v1/activitypub/reqsignature.go @@ -4,17 +4,132 @@ package activitypub import ( + "crypto" + "crypto/x509" + "database/sql" + "encoding/pem" + "errors" + "fmt" "net/http" + "net/url" + "forgejo.org/models/db" + "forgejo.org/models/forgefed" + "forgejo.org/models/user" + "forgejo.org/modules/activitypub" + fm "forgejo.org/modules/forgefed" "forgejo.org/modules/log" "forgejo.org/modules/setting" gitea_context "forgejo.org/services/context" "forgejo.org/services/federation" "github.com/42wim/httpsig" + ap "github.com/go-ap/activitypub" ) -func verifyHTTPUserOrInstanceSignature(ctx *gitea_context.APIContext) (authenticated bool, err error) { +func decodePublicKeyPem(pubKeyPem string) ([]byte, error) { + block, _ := pem.Decode([]byte(pubKeyPem)) + if block == nil || block.Type != "PUBLIC KEY" { + return nil, errors.New("could not decode publicKeyPem to PUBLIC KEY pem block type") + } + + return block.Bytes, nil +} + +func getFederatedUser(ctx *gitea_context.APIContext, person *ap.Person, federationHost *forgefed.FederationHost) (*user.FederatedUser, error) { + personID, err := fm.NewPersonID(person.ID.String(), string(federationHost.NodeInfo.SoftwareName)) + if err != nil { + return nil, err + } + _, federatedUser, err := user.FindFederatedUser(ctx, personID.ID, federationHost.ID) + if err != nil { + return nil, err + } + + if federatedUser != nil { + return federatedUser, nil + } + + _, newFederatedUser, err := federation.CreateUserFromAP(ctx, personID, federationHost.ID) + if err != nil { + return nil, err + } + + return newFederatedUser, nil +} + +func storePublicKey(ctx *gitea_context.APIContext, person *ap.Person, pubKeyBytes []byte) error { + federationHost, err := federation.GetFederationHostForURI(ctx, person.ID.String()) + if err != nil { + return err + } + + if person.Type == ap.ActivityVocabularyType("Application") { + federationHost.KeyID = sql.NullString{ + String: person.PublicKey.ID.String(), + Valid: true, + } + + federationHost.PublicKey = sql.Null[sql.RawBytes]{ + V: pubKeyBytes, + Valid: true, + } + + _, err = db.GetEngine(ctx).ID(federationHost.ID).Update(federationHost) + if err != nil { + return err + } + } else if person.Type == ap.ActivityVocabularyType("Person") { + federatedUser, err := getFederatedUser(ctx, person, federationHost) + if err != nil { + return err + } + + federatedUser.KeyID = sql.NullString{ + String: person.PublicKey.ID.String(), + Valid: true, + } + + federatedUser.PublicKey = sql.Null[sql.RawBytes]{ + V: pubKeyBytes, + Valid: true, + } + + _, err = db.GetEngine(ctx).ID(federatedUser.ID).Update(federatedUser) + if err != nil { + return err + } + } + + return nil +} + +func getPublicKeyFromResponse(b []byte, keyID *url.URL) (person *ap.Person, pubKeyBytes []byte, p crypto.PublicKey, err error) { + person = ap.PersonNew(ap.IRI(keyID.String())) + err = person.UnmarshalJSON(b) + if err != nil { + return nil, nil, nil, fmt.Errorf("ActivityStreams type cannot be converted to one known to have publicKey property: %w", err) + } + + pubKey := person.PublicKey + if pubKey.ID.String() != keyID.String() { + return nil, nil, nil, fmt.Errorf("cannot find publicKey with id: %s in %s", keyID, string(b)) + } + + pubKeyBytes, err = decodePublicKeyPem(pubKey.PublicKeyPem) + if err != nil { + return nil, nil, nil, err + } + + p, err = x509.ParsePKIXPublicKey(pubKeyBytes) + if err != nil { + return nil, nil, nil, err + } + + return person, pubKeyBytes, p, err +} + +func verifyHTTPSignatures(ctx *gitea_context.APIContext) (authenticated bool, err error) { if !setting.Federation.SignatureEnforced { return true, nil } @@ -27,64 +142,84 @@ func verifyHTTPUserOrInstanceSignature(ctx *gitea_context.APIContext) (authentic return false, err } + ID := v.KeyId() + idIRI, err := url.Parse(ID) + if err != nil { + return false, err + } + signatureAlgorithm := httpsig.Algorithm(setting.Federation.SignatureAlgorithms[0]) - pubKey, err := federation.FindOrCreateFederatedUserKey(ctx.Base, v.KeyId()) - if err != nil || pubKey == nil { - pubKey, err = federation.FindOrCreateFederationHostKey(ctx.Base, v.KeyId()) + + // 2. Fetch the public key of the other actor + // Try if the signing actor is an already known federated user + _, federationUser, err := user.FindFederatedUserByKeyID(ctx, idIRI.String()) + if err != nil { + return false, err + } + + if federationUser != nil && federationUser.PublicKey.Valid { + pubKey, err := x509.ParsePKIXPublicKey(federationUser.PublicKey.V) + if err != nil { + return false, err + } + + authenticated = v.Verify(pubKey, signatureAlgorithm) == nil + return authenticated, err + } + + // Try if the signing actor is an already known federation host + federationHost, err := forgefed.FindFederationHostByKeyID(ctx, idIRI.String()) + if err != nil { + return false, err + } + + if federationHost != nil && federationHost.PublicKey.Valid { + pubKey, err := x509.ParsePKIXPublicKey(federationHost.PublicKey.V) + if err != nil { + return false, err + } + + authenticated = v.Verify(pubKey, signatureAlgorithm) == nil + return authenticated, err + } + + // Fetch missing public key + actionsUser := user.NewAPServerActor() + clientFactory, err := activitypub.GetClientFactory(ctx) + if err != nil { + return false, err + } + + apClient, err := clientFactory.WithKeys(ctx, actionsUser, actionsUser.APActorKeyID()) + if err != nil { + return false, err + } + + b, err := apClient.GetBody(idIRI.String()) + if err != nil { + return false, err + } + + person, pubKeyBytes, pubKey, err := getPublicKeyFromResponse(b, idIRI) + if err != nil { + return false, err + } + + authenticated = v.Verify(pubKey, signatureAlgorithm) == nil + if authenticated { + err = storePublicKey(ctx, person, pubKeyBytes) if err != nil { return false, err } } - err = v.Verify(pubKey, signatureAlgorithm) - if err != nil { - return false, err - } - return true, nil -} - -func verifyHTTPUserSignature(ctx *gitea_context.APIContext) (authenticated bool, err error) { - if !setting.Federation.SignatureEnforced { - return true, nil - } - - r := ctx.Req - - // 1. Figure out what key we need to verify - v, err := httpsig.NewVerifier(r) - if err != nil { - return false, err - } - - signatureAlgorithm := httpsig.Algorithm(setting.Federation.SignatureAlgorithms[0]) - pubKey, err := federation.FindOrCreateFederatedUserKey(ctx.Base, v.KeyId()) - if err != nil { - return false, err - } - - err = v.Verify(pubKey, signatureAlgorithm) - if err != nil { - return false, err - } - return true, nil + return authenticated, err } // ReqHTTPSignature function -func ReqHTTPUserOrInstanceSignature() func(ctx *gitea_context.APIContext) { +func ReqHTTPSignature() func(ctx *gitea_context.APIContext) { return func(ctx *gitea_context.APIContext) { - if authenticated, err := verifyHTTPUserOrInstanceSignature(ctx); err != nil { - log.Warn("verifyHttpSignatures failed: %v", err) - ctx.Error(http.StatusBadRequest, "reqSignature", "request signature verification failed") - } else if !authenticated { - ctx.Error(http.StatusForbidden, "reqSignature", "request signature verification failed") - } - } -} - -// ReqHTTPSignature function -func ReqHTTPUserSignature() func(ctx *gitea_context.APIContext) { - return func(ctx *gitea_context.APIContext) { - if authenticated, err := verifyHTTPUserSignature(ctx); err != nil { + if authenticated, err := verifyHTTPSignatures(ctx); err != nil { log.Warn("verifyHttpSignatures failed: %v", err) ctx.Error(http.StatusBadRequest, "reqSignature", "request signature verification failed") } else if !authenticated { diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index fe13f85df4..bf08bdd249 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -92,7 +92,6 @@ import ( _ "forgejo.org/routers/api/v1/swagger" // for swagger generation "code.forgejo.org/go-chi/binding" - ap "github.com/go-ap/activitypub" ) func sudo() func(ctx *context.APIContext) { @@ -827,22 +826,24 @@ func Routes() *web.Route { if setting.Federation.Enabled { m.Get("/nodeinfo", misc.NodeInfo) m.Group("/activitypub", func() { + // deprecated, remove in 1.20, use /user-id/{user-id} instead + m.Group("/user/{username}", func() { + m.Get("", activitypub.ReqHTTPSignature(), activitypub.Person) + m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox) + }, context.UserAssignmentAPI(), checkTokenPublicOnly()) m.Group("/user-id/{user-id}", func() { - m.Get("", activitypub.ReqHTTPUserOrInstanceSignature(), activitypub.Person) - m.Post("/inbox", - activitypub.ReqHTTPUserSignature(), - bind(ap.Activity{}), - activitypub.PersonInbox) + m.Get("", activitypub.ReqHTTPSignature(), activitypub.Person) + m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox) }, context.UserIDAssignmentAPI(), checkTokenPublicOnly()) m.Group("/actor", func() { m.Get("", activitypub.Actor) - m.Post("/inbox", activitypub.ReqHTTPUserOrInstanceSignature(), activitypub.ActorInbox) + m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.ActorInbox) }) m.Group("/repository-id/{repository-id}", func() { - m.Get("", activitypub.ReqHTTPUserSignature(), activitypub.Repository) + m.Get("", activitypub.ReqHTTPSignature(), activitypub.Repository) m.Post("/inbox", bind(forgefed.ForgeLike{}), - activitypub.ReqHTTPUserSignature(), + activitypub.ReqHTTPSignature(), activitypub.RepositoryInbox) }, context.RepositoryIDAssignmentAPI()) }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryActivityPub)) diff --git a/routers/api/v1/repo/compare.go b/routers/api/v1/repo/compare.go index 7fc59ea171..9c941ea07f 100644 --- a/routers/api/v1/repo/compare.go +++ b/routers/api/v1/repo/compare.go @@ -64,7 +64,7 @@ func CompareDiff(ctx *context.APIContext) { } } - headRepository, headGitRepo, ci, _, _ := parseCompareInfo(ctx, api.CreatePullRequestOption{ + _, headGitRepo, ci, _, _ := parseCompareInfo(ctx, api.CreatePullRequestOption{ Base: infos[0], Head: infos[1], }) @@ -80,7 +80,7 @@ func CompareDiff(ctx *context.APIContext) { apiFiles := []*api.CommitAffectedFiles{} userCache := make(map[string]*user_model.User) for i := 0; i < len(ci.Commits); i++ { - apiCommit, err := convert.ToCommit(ctx, headRepository, headGitRepo, ci.Commits[i], userCache, + apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, ci.Commits[i], userCache, convert.ToCommitOptions{ Stat: true, Verification: verification, diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 442e109843..5495c4a6ba 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -121,12 +121,6 @@ func SearchIssues(ctx *context.APIContext) { // description: Number of items per page // type: integer // minimum: 0 - // - name: sort - // in: query - // description: Type of sort - // type: string - // enum: [relevance, latest, oldest, recentupdate, leastupdate, mostcomment, leastcomment, nearduedate, farduedate] - // default: latest // responses: // "200": // "$ref": "#/responses/IssueList" @@ -282,7 +276,7 @@ func SearchIssues(ctx *context.APIContext) { IsClosed: isClosed, IncludedAnyLabelIDs: includedAnyLabels, MilestoneIDs: includedMilestones, - SortBy: issue_indexer.ParseSortBy(ctx.FormString("sort"), issue_indexer.SortByCreatedDesc), + SortBy: issue_indexer.SortByCreatedDesc, } if since != 0 { @@ -311,10 +305,9 @@ func SearchIssues(ctx *context.APIContext) { } } - priorityRepoID := ctx.FormInt64("priority_repo_id") - if priorityRepoID > 0 { - searchOpt.PriorityRepoID = optional.Some(priorityRepoID) - } + // FIXME: It's unsupported to sort by priority repo when searching by indexer, + // it's indeed an regression, but I think it is worth to support filtering by indexer first. + _ = ctx.FormInt64("priority_repo_id") ids, total, err := issue_indexer.SearchIssues(ctx, searchOpt) if err != nil { diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index e7ff533d6a..c9dda124de 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -1084,6 +1084,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) err error ) + // If there is no head repository, it means pull request between same repository. headInfos := strings.Split(form.Head, ":") if len(headInfos) == 1 { isSameRepo = true @@ -1093,7 +1094,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) headUser, err = user_model.GetUserByName(ctx, headInfos[0]) if err != nil { if user_model.IsErrUserNotExist(err) { - ctx.NotFound(fmt.Errorf("the owner %s does not exist", headInfos[0])) + ctx.NotFound("GetUserByName") } else { ctx.Error(http.StatusInternalServerError, "GetUserByName", err) } @@ -1103,7 +1104,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) // The head repository can also point to the same repo isSameRepo = ctx.Repo.Owner.ID == headUser.ID } else { - ctx.NotFound(fmt.Errorf("the head part of {basehead} %s must contain zero or one colon (:) but contains %d", form.Head, len(headInfos)-1)) + ctx.NotFound() return nil, nil, nil, "", "" } @@ -1115,10 +1116,16 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) baseIsBranch := ctx.Repo.GitRepo.IsBranchExist(baseBranch) baseIsTag := ctx.Repo.GitRepo.IsTagExist(baseBranch) if !baseIsCommit && !baseIsBranch && !baseIsTag { - ctx.NotFound(fmt.Errorf("could not find '%s' to be a commit, branch or tag in the base repository %s/%s", baseBranch, baseRepo.Owner.Name, baseRepo.Name)) - return nil, nil, nil, "", "" + // Check for short SHA usage + if baseCommit, _ := ctx.Repo.GitRepo.GetCommit(baseBranch); baseCommit != nil { + baseBranch = baseCommit.ID.String() + } else { + ctx.NotFound("BaseNotExist") + return nil, nil, nil, "", "" + } } + // Check if current user has fork of repository or in the same repository. headRepo := repo_model.GetForkedRepo(ctx, headUser.ID, baseRepo.ID) if headRepo == nil && !isSameRepo { err := baseRepo.GetBaseRepo(ctx) @@ -1127,11 +1134,13 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) return nil, nil, nil, "", "" } + // Check if baseRepo's base repository is the same as headUser's repository. if baseRepo.BaseRepo == nil || baseRepo.BaseRepo.OwnerID != headUser.ID { log.Trace("parseCompareInfo[%d]: does not have fork or in same repository", baseRepo.ID) - ctx.NotFound(fmt.Errorf("%[1]s does not have a fork of %[2]s/%[3]s and %[2]s/%[3]s is not a fork of a repository from %[1]s", headUser.Name, baseRepo.Owner.Name, baseRepo.Name)) + ctx.NotFound("GetBaseRepo") return nil, nil, nil, "", "" } + // Assign headRepo so it can be used below. headRepo = baseRepo.BaseRepo } @@ -1193,20 +1202,21 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) } // Check if head branch is valid. - headIsCommit := headGitRepo.IsCommitExist(headBranch) - headIsBranch := headGitRepo.IsBranchExist(headBranch) - headIsTag := headGitRepo.IsTagExist(headBranch) + headIsCommit := ctx.Repo.GitRepo.IsCommitExist(headBranch) + headIsBranch := ctx.Repo.GitRepo.IsBranchExist(headBranch) + headIsTag := ctx.Repo.GitRepo.IsTagExist(headBranch) if !headIsCommit && !headIsBranch && !headIsTag { - ctx.NotFound(fmt.Errorf("could not find '%s' to be a commit, branch or tag in the head repository %s/%s", headBranch, headRepo.Owner.Name, headRepo.Name)) - return nil, nil, nil, "", "" + // Check if headBranch is short sha commit hash + if headCommit, _ := headGitRepo.GetCommit(headBranch); headCommit != nil { + headBranch = headCommit.ID.String() + } else { + headGitRepo.Close() + ctx.NotFound("IsRefExist", nil) + return nil, nil, nil, "", "" + } } headBranchRef := headBranch - if headIsBranch { - headBranchRef = git.BranchPrefix + headBranch - } else if headIsTag { - headBranchRef = git.TagPrefix + headBranch - } compareInfo, err := headGitRepo.GetCompareInfo(repo_model.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranchRef, headBranchRef, false, false) if err != nil { diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 7b6a00408a..bb4cf0f211 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -5,7 +5,6 @@ package repo import ( "encoding/base64" - "errors" "fmt" "net/http" "net/url" @@ -507,8 +506,11 @@ func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) // given tree entry, encoded with base64. Writes to ctx if an error occurs. func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) string { blob := entry.Blob() - content, err := blob.GetContentBase64(setting.API.DefaultMaxBlobSize) - if err != nil && !errors.As(err, &git.BlobTooLargeError{}) { + if blob.Size() > setting.API.DefaultMaxBlobSize { + return "" + } + content, err := blob.GetBlobContentBase64() + if err != nil { ctx.Error(http.StatusInternalServerError, "GetBlobContentBase64", err) return "" } diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index a856a7a00a..c7748b01c8 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -205,7 +205,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { // post update for agit pull request // FIXME: use pr.Flow to test whether it's an Agit PR or a GH PR - if refFullName.IsPull() { + if git.SupportProcReceive && refFullName.IsPull() { if repo == nil { repo = loadRepository(ctx, ownerName, repoName) if ctx.Written() { diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index 45992e8522..4c0e9a8551 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -205,7 +205,7 @@ func HookPreReceive(ctx *gitea_context.PrivateContext) { preReceiveBranch(ourCtx, oldCommitID, newCommitID, refFullName) case refFullName.IsTag(): preReceiveTag(ourCtx, oldCommitID, newCommitID, refFullName) - case refFullName.IsFor(): + case git.SupportProcReceive && refFullName.IsFor(): preReceiveFor(ourCtx, oldCommitID, newCommitID, refFullName) default: if ourCtx.isOverQuota { diff --git a/routers/private/hook_proc_receive.go b/routers/private/hook_proc_receive.go index 9f6e23f158..cd45794261 100644 --- a/routers/private/hook_proc_receive.go +++ b/routers/private/hook_proc_receive.go @@ -7,6 +7,7 @@ import ( "net/http" repo_model "forgejo.org/models/repo" + "forgejo.org/modules/git" "forgejo.org/modules/log" "forgejo.org/modules/private" "forgejo.org/modules/web" @@ -17,6 +18,10 @@ import ( // HookProcReceive proc-receive hook - only handles agit Proc-Receive requests at present func HookProcReceive(ctx *gitea_context.PrivateContext) { opts := web.GetForm(ctx).(*private.HookOptions) + if !git.SupportProcReceive { + ctx.Status(http.StatusNotFound) + return + } results, err := agit.ProcReceive(ctx, ctx.Repo.Repository, ctx.Repo.GitRepo, opts) if err != nil { diff --git a/routers/private/manager.go b/routers/private/manager.go index 90b48256df..7ab198f71b 100644 --- a/routers/private/manager.go +++ b/routers/private/manager.go @@ -145,7 +145,6 @@ func AddLogger(ctx *context.PrivateContext) { writerMode.Prefix, _ = opts.Config["prefix"].(string) writerMode.Expression, _ = opts.Config["expression"].(string) - writerMode.Exclusion, _ = opts.Config["exclusion"].(string) switch writerType { case "console": diff --git a/routers/private/serv.go b/routers/private/serv.go index a4029e354c..4c5b7bbccb 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -14,6 +14,7 @@ import ( repo_model "forgejo.org/models/repo" "forgejo.org/models/unit" user_model "forgejo.org/models/user" + "forgejo.org/modules/git" "forgejo.org/modules/log" "forgejo.org/modules/private" "forgejo.org/modules/setting" @@ -302,7 +303,7 @@ func ServCommand(ctx *context.PrivateContext) { // the permission check to read. The pre-receive hook will do another // permission check which ensure for non AGit flow references the write // permission is checked. - if unitType == unit.TypeCode && ctx.FormString("verb") == "git-receive-pack" { + if git.SupportProcReceive && unitType == unit.TypeCode && ctx.FormString("verb") == "git-receive-pack" { mode = perm.AccessModeRead } diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 7b09c92ee5..01e663a672 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -25,7 +25,7 @@ import ( "forgejo.org/services/context" "github.com/gorilla/feeds" - "github.com/inbucket/html2text" + "github.com/jaytaylor/html2text" ) func toBranchLink(ctx *context.Context, act *activities_model.Action) string { diff --git a/routers/web/misc/misc.go b/routers/web/misc/misc.go index 22fdccf79f..87b5247599 100644 --- a/routers/web/misc/misc.go +++ b/routers/web/misc/misc.go @@ -7,6 +7,7 @@ import ( "net/http" "path" + "forgejo.org/modules/git" "forgejo.org/modules/httpcache" "forgejo.org/modules/log" "forgejo.org/modules/setting" @@ -14,6 +15,10 @@ import ( ) func SSHInfo(rw http.ResponseWriter, req *http.Request) { + if !git.SupportProcReceive { + rw.WriteHeader(http.StatusNotFound) + return + } rw.Header().Set("content-type", "text/json;charset=UTF-8") _, err := rw.Write([]byte(`{"type":"agit","version":1}`)) if err != nil { diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index f4cc2a2cea..ccdd59f2dd 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -82,19 +82,19 @@ func RefBlame(ctx *context.Context) { return } + ctx.Data["NumLinesSet"] = true + ctx.Data["NumLines"], err = blob.GetBlobLineCount() + if err != nil { + ctx.ServerError("GetBlobLineCount", err) + return + } + result, err := performBlame(ctx, ctx.Repo.Commit, ctx.Repo.TreePath, ctx.FormBool("bypass-blame-ignore")) if err != nil { ctx.ServerError("performBlame", err) return } - ctx.Data["NumLinesSet"] = true - numLines := 0 - for _, p := range result.Parts { - numLines += len(p.Lines) - } - ctx.Data["NumLines"] = numLines - ctx.Data["UsesIgnoreRevs"] = result.UsesIgnoreRevs ctx.Data["FaultyIgnoreRevsFile"] = result.FaultyIgnoreRevsFile diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 59538d8a0e..de2e29ab9f 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -312,16 +312,22 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo { baseIsTag := ctx.Repo.GitRepo.IsTagExist(ci.BaseBranch) if !baseIsCommit && !baseIsBranch && !baseIsTag { - if ci.BaseBranch == ctx.Repo.GetObjectFormat().EmptyObjectID().String() { + // Check if baseBranch is short sha commit hash + if baseCommit, _ := ctx.Repo.GitRepo.GetCommit(ci.BaseBranch); baseCommit != nil { + ci.BaseBranch = baseCommit.ID.String() + ctx.Data["BaseBranch"] = ci.BaseBranch + baseIsCommit = true + } else if ci.BaseBranch == ctx.Repo.GetObjectFormat().EmptyObjectID().String() { if isSameRepo { ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch)) } else { ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadRepo.FullName()) + ":" + util.PathEscapeSegments(ci.HeadBranch)) } + return nil } else { ctx.NotFound("IsRefExist", nil) + return nil } - return nil } ctx.Data["BaseIsCommit"] = baseIsCommit ctx.Data["BaseIsBranch"] = baseIsBranch @@ -508,8 +514,15 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo { headIsBranch := ci.HeadGitRepo.IsBranchExist(ci.HeadBranch) headIsTag := ci.HeadGitRepo.IsTagExist(ci.HeadBranch) if !headIsCommit && !headIsBranch && !headIsTag { - ctx.NotFound("IsRefExist", nil) - return nil + // Check if headBranch is short sha commit hash + if headCommit, _ := ci.HeadGitRepo.GetCommit(ci.HeadBranch); headCommit != nil { + ci.HeadBranch = headCommit.ID.String() + ctx.Data["HeadBranch"] = ci.HeadBranch + headIsCommit = true + } else { + ctx.NotFound("IsRefExist", nil) + return nil + } } ctx.Data["HeadIsCommit"] = headIsCommit ctx.Data["HeadIsBranch"] = headIsBranch diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index 3e3cb0016d..5114cc9c05 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -189,7 +189,7 @@ func editFile(ctx *context.Context, isNewFile bool) { buf = buf[:n] // Only some file types are editable online as text. - if !typesniffer.DetectContentType(buf, blob.Name()).IsRepresentableAsText() { + if !typesniffer.DetectContentType(buf).IsRepresentableAsText() { ctx.NotFound("typesniffer.IsRepresentableAsText", nil) return } diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index 42302d0e02..650b1d88f4 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -183,7 +183,9 @@ func httpBase(ctx *context.Context) *serviceHandler { if repoExist { // Because of special ref "refs/for" .. , need delay write permission check - accessMode = perm.AccessModeRead + if git.SupportProcReceive { + accessMode = perm.AccessModeRead + } if ctx.Data["IsActionsToken"] == true { taskID := ctx.Data["ActionsTaskID"].(int64) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index a4f6f97a05..5e228507c0 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -2775,7 +2775,7 @@ func SearchIssues(ctx *context.Context) { IncludedAnyLabelIDs: includedAnyLabels, MilestoneIDs: includedMilestones, ProjectID: projectID, - SortBy: issue_indexer.ParseSortBy(ctx.FormString("sort"), issue_indexer.SortByCreatedDesc), + SortBy: issue_indexer.SortByCreatedDesc, } if since != 0 { @@ -2804,10 +2804,9 @@ func SearchIssues(ctx *context.Context) { } } - priorityRepoID := ctx.FormInt64("priority_repo_id") - if priorityRepoID > 0 { - searchOpt.PriorityRepoID = optional.Some(priorityRepoID) - } + // FIXME: It's unsupported to sort by priority repo when searching by indexer, + // it's indeed an regression, but I think it is worth to support filtering by indexer first. + _ = ctx.FormInt64("priority_repo_id") ids, total, err := issue_indexer.SearchIssues(ctx, searchOpt) if err != nil { @@ -2945,7 +2944,7 @@ func ListIssues(ctx *context.Context) { IsPull: isPull, IsClosed: isClosed, ProjectID: projectID, - SortBy: issue_indexer.ParseSortBy(ctx.FormString("sort"), issue_indexer.SortByCreatedDesc), + SortBy: issue_indexer.SortByCreatedDesc, } if since != 0 { searchOpt.UpdatedAfterUnix = optional.Some(since) @@ -3593,9 +3592,9 @@ func GetIssueAttachments(ctx *context.Context) { if ctx.Written() { return } - attachments := make([]*api.WebAttachment, len(issue.Attachments)) + attachments := make([]*api.Attachment, len(issue.Attachments)) for i := 0; i < len(issue.Attachments); i++ { - attachments[i] = convert.ToWebAttachment(ctx.Repo.Repository, issue.Attachments[i]) + attachments[i] = convert.ToAttachment(ctx.Repo.Repository, issue.Attachments[i]) } ctx.JSON(http.StatusOK, attachments) } @@ -3628,13 +3627,13 @@ func GetCommentAttachments(ctx *context.Context) { return } + attachments := make([]*api.Attachment, 0) if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return } - attachments := make([]*api.WebAttachment, len(comment.Attachments)) for i := 0; i < len(comment.Attachments); i++ { - attachments[i] = convert.ToWebAttachment(ctx.Repo.Repository, comment.Attachments[i]) + attachments = append(attachments, convert.ToAttachment(ctx.Repo.Repository, comment.Attachments[i])) } ctx.JSON(http.StatusOK, attachments) } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 4e365f24ea..fd18646211 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -996,13 +996,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi ctx.Data["Verification"] = verification ctx.Data["Author"] = user_model.ValidateCommitWithEmail(ctx, curCommit) - if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) { - return repo_model.IsOwnerMemberCollaborator(ctx, ctx.Repo.Repository, user.ID) - }, nil); err != nil { - ctx.ServerError("CalculateTrustStatus", err) - return - } - note := &git.Note{} err = git.GetNote(ctx, ctx.Repo.GitRepo, specifiedEndCommit, note) if err == nil { diff --git a/routers/web/repo/render.go b/routers/web/repo/render.go index 05eeadc519..b31e2e203a 100644 --- a/routers/web/repo/render.go +++ b/routers/web/repo/render.go @@ -41,7 +41,7 @@ func RenderFile(ctx *context.Context) { n, _ := util.ReadAtMost(dataRc, buf) buf = buf[:n] - st := typesniffer.DetectContentType(buf, blob.Name()) + st := typesniffer.DetectContentType(buf) isTextFile := st.IsText() rd := charset.ToUTF8WithFallbackReader(io.MultiReader(bytes.NewReader(buf), dataRc), charset.ConvertOpts{}) diff --git a/routers/web/repo/setting/avatar.go b/routers/web/repo/setting/avatar.go index 20e211316d..84d7cccdb8 100644 --- a/routers/web/repo/setting/avatar.go +++ b/routers/web/repo/setting/avatar.go @@ -45,7 +45,7 @@ func UpdateAvatarSetting(ctx *context.Context, form forms.AvatarForm) error { if err != nil { return fmt.Errorf("io.ReadAll: %w", err) } - st := typesniffer.DetectContentType(data, "") + st := typesniffer.DetectContentType(data) if !st.IsImage() || st.IsSvgImage() { return errors.New(ctx.Locale.TrString("settings.uploaded_avatar_not_a_image")) } diff --git a/routers/web/repo/setting/lfs.go b/routers/web/repo/setting/lfs.go index 9930d03e8e..b9cb86bd08 100644 --- a/routers/web/repo/setting/lfs.go +++ b/routers/web/repo/setting/lfs.go @@ -291,7 +291,7 @@ func LFSFileGet(ctx *context.Context) { } buf = buf[:n] - st := typesniffer.DetectContentType(buf, "") + st := typesniffer.DetectContentType(buf) ctx.Data["IsTextFile"] = st.IsText() isRepresentableAsText := st.IsRepresentableAsText() diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index d00f85a134..bb3e1388a8 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -228,7 +228,7 @@ func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) ([]byte, n, _ := util.ReadAtMost(dataRc, buf) buf = buf[:n] - st := typesniffer.DetectContentType(buf, blob.Name()) + st := typesniffer.DetectContentType(buf) isTextFile := st.IsText() // FIXME: what happens when README file is an image? @@ -262,7 +262,7 @@ func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) ([]byte, } buf = buf[:n] - st = typesniffer.DetectContentType(buf, blob.Name()) + st = typesniffer.DetectContentType(buf) return buf, dataRc, &fileInfo{st.IsText(), true, meta.Size, &meta.Pointer, st}, nil } diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index e0ce88b582..400ee71f08 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -151,7 +151,7 @@ func UpdateAvatarSetting(ctx *context.Context, form *forms.AvatarForm, ctxUser * return fmt.Errorf("io.ReadAll: %w", err) } - st := typesniffer.DetectContentType(data, "") + st := typesniffer.DetectContentType(data) if !st.IsImage() || st.IsSvgImage() { return errors.New(ctx.Locale.TrString("settings.uploaded_avatar_not_a_image")) } diff --git a/routers/web/webfinger.go b/routers/web/webfinger.go index 372c08f7d8..be3c2925fe 100644 --- a/routers/web/webfinger.go +++ b/routers/web/webfinger.go @@ -58,33 +58,7 @@ func WebfingerQuery(ctx *context.Context) { return } - // Instance actor - if parts[0] == "ghost" { - aliases := []string{ - appURL.String() + "api/v1/activitypub/actor", - } - - links := []*webfingerLink{ - { - Rel: "self", - Type: "application/activity+json", - Href: appURL.String() + "api/v1/activitypub/actor", - }, - } - - ctx.Resp.Header().Add("Access-Control-Allow-Origin", "*") - ctx.JSON(http.StatusOK, &webfingerJRD{ - Subject: fmt.Sprintf("acct:%s@%s", "ghost", appURL.Host), - Aliases: aliases, - Links: links, - }) - ctx.Resp.Header().Set("Content-Type", "application/jrd+json") - - return - } - u, err = user_model.GetUserByName(ctx, parts[0]) - case "mailto": u, err = user_model.GetUserByEmail(ctx, resource.Opaque) if u != nil && u.KeepEmailPrivate { diff --git a/services/actions/notifier.go b/services/actions/notifier.go index a5bac730be..f1e9a6d7e9 100644 --- a/services/actions/notifier.go +++ b/services/actions/notifier.go @@ -788,7 +788,7 @@ func (n *actionsNotifier) MigrateRepository(ctx context.Context, doer, u *user_m // the ActionRun of the same workflow that finished before priorRun/updatedRun. func sendActionRunNowDoneNotificationIfNeeded(ctx context.Context, priorRun, updatedRun *actions_model.ActionRun) error { if !priorRun.Status.IsDone() && updatedRun.Status.IsDone() { - lastRun, err := actions_model.GetRunBefore(ctx, updatedRun) + lastRun, err := actions_model.GetRunBefore(ctx, updatedRun.RepoID, updatedRun.Stopped) if err != nil && !errors.Is(err, util.ErrNotExist) { return err } diff --git a/services/context/repo.go b/services/context/repo.go index c8876d7166..cce3a5fa70 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -644,11 +644,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc { ctx.Data["OpenGraphImageURL"] = repo.SummaryCardURL() ctx.Data["OpenGraphImageWidth"] = cardWidth ctx.Data["OpenGraphImageHeight"] = cardHeight - if util.IsEmptyString(repo.Description) { - ctx.Data["OpenGraphImageAltText"] = ctx.Tr("repo.summary_card_alt", repo.FullName()) - } else { - ctx.Data["OpenGraphImageAltText"] = ctx.Tr("og.repo.summary_card.alt_description", repo.FullName(), repo.Description) - } + ctx.Data["OpenGraphImageAltText"] = ctx.Tr("repo.summary_card_alt", repo.FullName()) if repo.IsFork { RetrieveBaseRepo(ctx, repo) diff --git a/services/convert/attachment.go b/services/convert/attachment.go index 74ae7c509c..6617aac906 100644 --- a/services/convert/attachment.go +++ b/services/convert/attachment.go @@ -4,9 +4,6 @@ package convert import ( - "mime" - "path/filepath" - repo_model "forgejo.org/models/repo" api "forgejo.org/modules/structs" ) @@ -23,13 +20,9 @@ func APIAssetDownloadURL(repo *repo_model.Repository, attach *repo_model.Attachm return attach.DownloadURL() } -// ToWebAttachment converts models.Attachment to api.WebAttachment for API usage -func ToWebAttachment(repo *repo_model.Repository, a *repo_model.Attachment) *api.WebAttachment { - attachment := toAttachment(repo, a, WebAssetDownloadURL) - return &api.WebAttachment{ - Attachment: attachment, - MimeType: mime.TypeByExtension(filepath.Ext(attachment.Name)), - } +// ToAttachment converts models.Attachment to api.Attachment for API usage +func ToAttachment(repo *repo_model.Repository, a *repo_model.Attachment) *api.Attachment { + return toAttachment(repo, a, WebAssetDownloadURL) } // ToAPIAttachment converts models.Attachment to api.Attachment for API usage diff --git a/services/convert/attachment_test.go b/services/convert/attachment_test.go deleted file mode 100644 index d7bf0c1ee7..0000000000 --- a/services/convert/attachment_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2025 The Forgejo Authors. All rights reserved. -// SPDX-License-Identifier: GPL-3.0-or-later - -package convert - -import ( - "fmt" - "testing" - "time" - - repo_model "forgejo.org/models/repo" - "forgejo.org/models/unittest" - "forgejo.org/modules/setting" - api "forgejo.org/modules/structs" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestToWebAttachment(t *testing.T) { - require.NoError(t, unittest.PrepareTestDatabase()) - headRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - attachment := &repo_model.Attachment{ - ID: 10, - UUID: "uuidxxx", - RepoID: 1, - IssueID: 1, - ReleaseID: 0, - UploaderID: 0, - CommentID: 0, - Name: "test.png", - DownloadCount: 90, - Size: 30, - NoAutoTime: false, - CreatedUnix: 9342, - CustomDownloadURL: "", - ExternalURL: "", - } - - webAttachment := ToWebAttachment(headRepo, attachment) - - assert.NotNil(t, webAttachment) - assert.Equal(t, &api.WebAttachment{ - Attachment: &api.Attachment{ - ID: 10, - Name: "test.png", - Created: time.Unix(9342, 0), - DownloadCount: 90, - Size: 30, - UUID: "uuidxxx", - DownloadURL: fmt.Sprintf("%sattachments/uuidxxx", setting.AppURL), - Type: "attachment", - }, - MimeType: "image/png", - }, webAttachment) -} diff --git a/services/federation/federation_service.go b/services/federation/federation_service.go index b71d8d2575..a3b719d1a7 100644 --- a/services/federation/federation_service.go +++ b/services/federation/federation_service.go @@ -5,12 +5,15 @@ package federation import ( "context" - "database/sql" + "errors" "fmt" + "net/http" "net/url" "strings" + "time" "forgejo.org/models/forgefed" + "forgejo.org/models/repo" "forgejo.org/models/user" "forgejo.org/modules/activitypub" "forgejo.org/modules/auth/password" @@ -18,84 +21,91 @@ import ( "forgejo.org/modules/log" "forgejo.org/modules/setting" "forgejo.org/modules/validation" - context_service "forgejo.org/services/context" "github.com/google/uuid" ) -func Init() error { - return nil -} +// ProcessLikeActivity receives a ForgeLike activity and does the following: +// Validation of the activity +// Creation of a (remote) federationHost if not existing +// Creation of a forgefed Person if not existing +// Validation of incoming RepositoryID against Local RepositoryID +// Star the repo if it wasn't already stared +// Do some mitigation against out of order attacks +func ProcessLikeActivity(ctx context.Context, form any, repositoryID int64) (int, string, error) { + activity := form.(*fm.ForgeLike) + if res, err := validation.IsValid(activity); !res { + return http.StatusNotAcceptable, "Invalid activity", err + } + log.Info("Activity validated:%v", activity) -func FindOrCreateFederationHost(ctx *context_service.Base, actorURI string) (*forgefed.FederationHost, error) { - rawActorID, err := fm.NewActorID(actorURI) + // parse actorID (person) + actorURI := activity.Actor.GetID().String() + log.Info("actorURI was: %v", actorURI) + federationHost, err := GetFederationHostForURI(ctx, actorURI) if err != nil { - return nil, err + return http.StatusInternalServerError, "Wrong FederationHost", err } - federationHost, err := forgefed.FindFederationHostByFqdnAndPort(ctx, rawActorID.Host, rawActorID.HostPort) - if err != nil { - return nil, err - } - if federationHost == nil { - result, err := createFederationHostFromAP(ctx, rawActorID) - if err != nil { - return nil, err - } - federationHost = result - } - return federationHost, nil -} - -func FindOrCreateFederatedUser(ctx *context_service.Base, actorURI string) (*user.User, *user.FederatedUser, *forgefed.FederationHost, error) { - user, federatedUser, federationHost, err := findFederatedUser(ctx, actorURI) - if err != nil { - return nil, nil, nil, err - } - personID, err := fm.NewPersonID(actorURI, string(federationHost.NodeInfo.SoftwareName)) - if err != nil { - return nil, nil, nil, err - } - - if user != nil { - log.Trace("Found local federatedUser: %#v", user) - } else { - user, federatedUser, err = createUserFromAP(ctx, personID, federationHost.ID) - if err != nil { - return nil, nil, nil, err - } - log.Trace("Created federatedUser from ap: %#v", user) - } - log.Trace("Got user: %v", user.Name) - - return user, federatedUser, federationHost, nil -} - -func findFederatedUser(ctx *context_service.Base, actorURI string) (*user.User, *user.FederatedUser, *forgefed.FederationHost, error) { - federationHost, err := FindOrCreateFederationHost(ctx, actorURI) - if err != nil { - return nil, nil, nil, err + if !activity.IsNewer(federationHost.LatestActivity) { + return http.StatusNotAcceptable, "Activity out of order.", errors.New("Activity already processed") } actorID, err := fm.NewPersonID(actorURI, string(federationHost.NodeInfo.SoftwareName)) if err != nil { - return nil, nil, nil, err + return http.StatusNotAcceptable, "Invalid PersonID", err } + log.Info("Actor accepted:%v", actorID) - user, federatedUser, err := user.FindFederatedUser(ctx, actorID.ID, federationHost.ID) + // parse objectID (repository) + objectID, err := fm.NewRepositoryID(activity.Object.GetID().String(), string(forgefed.ForgejoSourceType)) if err != nil { - return nil, nil, nil, err + return http.StatusNotAcceptable, "Invalid objectId", err + } + if objectID.ID != fmt.Sprint(repositoryID) { + return http.StatusNotAcceptable, "Invalid objectId", err + } + log.Info("Object accepted:%v", objectID) + + // Check if user already exists + user, _, err := user.FindFederatedUser(ctx, actorID.ID, federationHost.ID) + if err != nil { + return http.StatusInternalServerError, "Searching for user failed", err + } + if user != nil { + log.Info("Found local federatedUser: %v", user) + } else { + user, _, err = CreateUserFromAP(ctx, actorID, federationHost.ID) + if err != nil { + return http.StatusInternalServerError, "Error creating federatedUser", err + } + log.Info("Created federatedUser from ap: %v", user) + } + log.Info("Got user:%v", user.Name) + + // execute the activity if the repo was not stared already + alreadyStared := repo.IsStaring(ctx, user.ID, repositoryID) + if !alreadyStared { + err = repo.StarRepo(ctx, user.ID, repositoryID, true) + if err != nil { + return http.StatusNotAcceptable, "Error staring", err + } + } + federationHost.LatestActivity = activity.StartTime + err = forgefed.UpdateFederationHost(ctx, federationHost) + if err != nil { + return http.StatusNotAcceptable, "Error updating federatedHost", err } - return user, federatedUser, federationHost, nil + return 0, "", nil } -func createFederationHostFromAP(ctx context.Context, actorID fm.ActorID) (*forgefed.FederationHost, error) { +func CreateFederationHostFromAP(ctx context.Context, actorID fm.ActorID) (*forgefed.FederationHost, error) { actionsUser := user.NewAPServerActor() clientFactory, err := activitypub.GetClientFactory(ctx) if err != nil { return nil, err } - client, err := clientFactory.WithKeys(ctx, actionsUser, actionsUser.KeyID()) + client, err := clientFactory.WithKeys(ctx, actionsUser, actionsUser.APActorKeyID()) if err != nil { return nil, err } @@ -120,7 +130,6 @@ func createFederationHostFromAP(ctx context.Context, actorID fm.ActorID) (*forge return nil, err } - // TODO: we should get key material here also to have it immediately result, err := forgefed.NewFederationHost(actorID.Host, nodeInfo, actorID.HostPort, actorID.HostSchema) if err != nil { return nil, err @@ -134,14 +143,34 @@ func createFederationHostFromAP(ctx context.Context, actorID fm.ActorID) (*forge return &result, nil } -func fetchUserFromAP(ctx context.Context, personID fm.PersonID, federationHostID int64) (*user.User, *user.FederatedUser, error) { +func GetFederationHostForURI(ctx context.Context, actorURI string) (*forgefed.FederationHost, error) { + log.Info("Input was: %v", actorURI) + rawActorID, err := fm.NewActorID(actorURI) + if err != nil { + return nil, err + } + federationHost, err := forgefed.FindFederationHostByFqdnAndPort(ctx, rawActorID.Host, rawActorID.HostPort) + if err != nil { + return nil, err + } + if federationHost == nil { + result, err := CreateFederationHostFromAP(ctx, rawActorID) + if err != nil { + return nil, err + } + federationHost = result + } + return federationHost, nil +} + +func CreateUserFromAP(ctx context.Context, personID fm.PersonID, federationHostID int64) (*user.User, *user.FederatedUser, error) { actionsUser := user.NewAPServerActor() clientFactory, err := activitypub.GetClientFactory(ctx) if err != nil { return nil, nil, err } - apClient, err := clientFactory.WithKeys(ctx, actionsUser, actionsUser.KeyID()) + apClient, err := clientFactory.WithKeys(ctx, actionsUser, actionsUser.APActorKeyID()) if err != nil { return nil, nil, err } @@ -187,11 +216,6 @@ func fetchUserFromAP(ctx context.Context, personID fm.PersonID, federationHostID return nil, nil, err } - pubKeyBytes, err := decodePublicKeyPem(person.PublicKey.PublicKeyPem) - if err != nil { - return nil, nil, err - } - newUser := user.User{ LowerName: strings.ToLower(name), Name: name, @@ -210,30 +234,86 @@ func fetchUserFromAP(ctx context.Context, personID fm.PersonID, federationHostID FederationHostID: federationHostID, InboxPath: inbox.Path, NormalizedOriginalURL: personID.AsURI(), - KeyID: sql.NullString{ - String: person.PublicKey.ID.String(), - Valid: true, - }, - PublicKey: sql.Null[sql.RawBytes]{ - V: pubKeyBytes, - Valid: true, - }, } - log.Info("Fetch federatedUser:%q", federatedUser) - return &newUser, &federatedUser, nil -} - -func createUserFromAP(ctx context.Context, personID fm.PersonID, federationHostID int64) (*user.User, *user.FederatedUser, error) { - newUser, federatedUser, err := fetchUserFromAP(ctx, personID, federationHostID) - if err != nil { - return nil, nil, err - } - err = user.CreateFederatedUser(ctx, newUser, federatedUser) + err = user.CreateFederatedUser(ctx, &newUser, &federatedUser) if err != nil { return nil, nil, err } log.Info("Created federatedUser:%q", federatedUser) - return newUser, federatedUser, nil + return &newUser, &federatedUser, nil +} + +// Create or update a list of FollowingRepo structs +func StoreFollowingRepoList(ctx context.Context, localRepoID int64, followingRepoList []string) (int, string, error) { + followingRepos := make([]*repo.FollowingRepo, 0, len(followingRepoList)) + for _, uri := range followingRepoList { + federationHost, err := GetFederationHostForURI(ctx, uri) + if err != nil { + return http.StatusInternalServerError, "Wrong FederationHost", err + } + followingRepoID, err := fm.NewRepositoryID(uri, string(federationHost.NodeInfo.SoftwareName)) + if err != nil { + return http.StatusNotAcceptable, "Invalid federated repo", err + } + followingRepo, err := repo.NewFollowingRepo(localRepoID, followingRepoID.ID, federationHost.ID, uri) + if err != nil { + return http.StatusNotAcceptable, "Invalid federated repo", err + } + followingRepos = append(followingRepos, &followingRepo) + } + + if err := repo.StoreFollowingRepos(ctx, localRepoID, followingRepos); err != nil { + return 0, "", err + } + + return 0, "", nil +} + +func DeleteFollowingRepos(ctx context.Context, localRepoID int64) error { + return repo.StoreFollowingRepos(ctx, localRepoID, []*repo.FollowingRepo{}) +} + +func SendLikeActivities(ctx context.Context, doer user.User, repoID int64) error { + followingRepos, err := repo.FindFollowingReposByRepoID(ctx, repoID) + log.Info("Federated Repos is: %v", followingRepos) + if err != nil { + return err + } + + likeActivityList := make([]fm.ForgeLike, 0) + for _, followingRepo := range followingRepos { + log.Info("Found following repo: %v", followingRepo) + target := followingRepo.URI + likeActivity, err := fm.NewForgeLike(doer.APActorID(), target, time.Now()) + if err != nil { + return err + } + likeActivityList = append(likeActivityList, likeActivity) + } + + apclientFactory, err := activitypub.GetClientFactory(ctx) + if err != nil { + return err + } + + apclient, err := apclientFactory.WithKeys(ctx, &doer, doer.APActorKeyID()) + if err != nil { + return err + } + for i, activity := range likeActivityList { + activity.StartTime = activity.StartTime.Add(time.Duration(i) * time.Second) + json, err := activity.MarshalJSON() + if err != nil { + return err + } + + _, err = apclient.Post(json, fmt.Sprintf("%s/inbox", activity.Object)) + if err != nil { + log.Error("error %v while sending activity: %q", err, activity) + } + } + + return nil } diff --git a/services/federation/repo_like.go b/services/federation/repo_like.go deleted file mode 100644 index c1e6500c61..0000000000 --- a/services/federation/repo_like.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2024 The Forgejo Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package federation - -import ( - "context" - "errors" - "fmt" - "net/http" - "time" - - "forgejo.org/models/forgefed" - "forgejo.org/models/repo" - "forgejo.org/models/user" - "forgejo.org/modules/activitypub" - fm "forgejo.org/modules/forgefed" - "forgejo.org/modules/log" - "forgejo.org/modules/validation" - context_service "forgejo.org/services/context" -) - -// ProcessLikeActivity receives a ForgeLike activity and does the following: -// Validation of the activity -// Creation of a (remote) federationHost if not existing -// Creation of a forgefed Person if not existing -// Validation of incoming RepositoryID against Local RepositoryID -// Star the repo if it wasn't already stared -// Do some mitigation against out of order attacks -func ProcessLikeActivity(ctx *context_service.APIContext, form any, repositoryID int64) (int, string, error) { - activity := form.(*fm.ForgeLike) - if res, err := validation.IsValid(activity); !res { - return http.StatusNotAcceptable, "Invalid activity", err - } - log.Trace("Activity validated: %#v", activity) - - // parse actorID (person) - actorURI := activity.Actor.GetID().String() - user, _, federationHost, err := FindOrCreateFederatedUser(ctx.Base, actorURI) - if err != nil { - ctx.Error(http.StatusNotAcceptable, "Federated user not found", err) - return http.StatusInternalServerError, "FindOrCreateFederatedUser", err - } - - if !activity.IsNewer(federationHost.LatestActivity) { - return http.StatusNotAcceptable, "Activity out of order.", errors.New("Activity already processed") - } - - // parse objectID (repository) - objectID, err := fm.NewRepositoryID(activity.Object.GetID().String(), string(forgefed.ForgejoSourceType)) - if err != nil { - return http.StatusNotAcceptable, "Invalid objectId", err - } - if objectID.ID != fmt.Sprint(repositoryID) { - return http.StatusNotAcceptable, "Invalid objectId", err - } - log.Trace("Object accepted: %#v", objectID) - - // execute the activity if the repo was not stared already - alreadyStared := repo.IsStaring(ctx, user.ID, repositoryID) - if !alreadyStared { - err = repo.StarRepo(ctx, user.ID, repositoryID, true) - if err != nil { - return http.StatusNotAcceptable, "Error staring", err - } - } - federationHost.LatestActivity = activity.StartTime - err = forgefed.UpdateFederationHost(ctx, federationHost) - if err != nil { - return http.StatusNotAcceptable, "Error updating federatedHost", err - } - - return 0, "", nil -} - -// Create or update a list of FollowingRepo structs -func StoreFollowingRepoList(ctx *context_service.Context, localRepoID int64, followingRepoList []string) (int, string, error) { - followingRepos := make([]*repo.FollowingRepo, 0, len(followingRepoList)) - for _, uri := range followingRepoList { - federationHost, err := FindOrCreateFederationHost(ctx.Base, uri) - if err != nil { - return http.StatusInternalServerError, "Wrong FederationHost", err - } - followingRepoID, err := fm.NewRepositoryID(uri, string(federationHost.NodeInfo.SoftwareName)) - if err != nil { - return http.StatusNotAcceptable, "Invalid federated repo", err - } - followingRepo, err := repo.NewFollowingRepo(localRepoID, followingRepoID.ID, federationHost.ID, uri) - if err != nil { - return http.StatusNotAcceptable, "Invalid federated repo", err - } - followingRepos = append(followingRepos, &followingRepo) - } - - if err := repo.StoreFollowingRepos(ctx, localRepoID, followingRepos); err != nil { - return 0, "", err - } - - return 0, "", nil -} - -func DeleteFollowingRepos(ctx context.Context, localRepoID int64) error { - return repo.StoreFollowingRepos(ctx, localRepoID, []*repo.FollowingRepo{}) -} - -func SendLikeActivities(ctx context.Context, doer user.User, repoID int64) error { - followingRepos, err := repo.FindFollowingReposByRepoID(ctx, repoID) - log.Trace("Federated Repos is: %#v", followingRepos) - if err != nil { - return err - } - - likeActivityList := make([]fm.ForgeLike, 0) - for _, followingRepo := range followingRepos { - log.Trace("Found following repo: %#v", followingRepo) - target := followingRepo.URI - likeActivity, err := fm.NewForgeLike(doer.APActorID(), target, time.Now()) - if err != nil { - return err - } - likeActivityList = append(likeActivityList, likeActivity) - } - - apclientFactory, err := activitypub.GetClientFactory(ctx) - if err != nil { - return err - } - apclient, err := apclientFactory.WithKeys(ctx, &doer, doer.APActorID()+"#main-key") - if err != nil { - return err - } - for i, activity := range likeActivityList { - activity.StartTime = activity.StartTime.Add(time.Duration(i) * time.Second) - json, err := activity.MarshalJSON() - if err != nil { - return err - } - - _, err = apclient.Post(json, fmt.Sprintf("%v/inbox", activity.Object)) - if err != nil { - log.Error("error %v while sending activity: %#v", err, activity) - } - } - - return nil -} diff --git a/services/federation/signature_service.go b/services/federation/signature_service.go deleted file mode 100644 index e5102b89d8..0000000000 --- a/services/federation/signature_service.go +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2024, 2025 The Forgejo Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package federation - -import ( - "crypto/x509" - "database/sql" - "encoding/pem" - "errors" - "fmt" - "net/url" - - "forgejo.org/models/forgefed" - "forgejo.org/models/user" - "forgejo.org/modules/activitypub" - fm "forgejo.org/modules/forgefed" - context_service "forgejo.org/services/context" - - ap "github.com/go-ap/activitypub" -) - -// Factory function for ActorID. Created struct is asserted to be valid -func NewActorIDFromKeyID(ctx *context_service.Base, uri string) (fm.ActorID, error) { - parsedURI, err := url.Parse(uri) - parsedURI.Fragment = "" - if err != nil { - return fm.ActorID{}, err - } - - actionsUser := user.NewAPServerActor() - clientFactory, err := activitypub.GetClientFactory(ctx) - if err != nil { - return fm.ActorID{}, err - } - - apClient, err := clientFactory.WithKeys(ctx, actionsUser, actionsUser.KeyID()) - if err != nil { - return fm.ActorID{}, err - } - - userResponse, err := apClient.GetBody(parsedURI.String()) - if err != nil { - return fm.ActorID{}, err - } - - var actor ap.Actor - err = actor.UnmarshalJSON(userResponse) - if err != nil { - return fm.ActorID{}, err - } - - result, err := fm.NewActorID(actor.PublicKey.Owner.String()) - return result, err -} - -func FindOrCreateFederatedUserKey(ctx *context_service.Base, keyID string) (pubKey any, err error) { - var federatedUser *user.FederatedUser - var keyURL *url.URL - - keyURL, err = url.Parse(keyID) - if err != nil { - return nil, err - } - - // Try if the signing actor is an already known federated user - _, federatedUser, err = user.FindFederatedUserByKeyID(ctx, keyURL.String()) - if err != nil { - return nil, err - } - - if federatedUser == nil { - rawActorID, err := NewActorIDFromKeyID(ctx, keyID) - if err != nil { - return nil, err - } - - _, federatedUser, _, err = FindOrCreateFederatedUser(ctx, rawActorID.AsURI()) - if err != nil { - return nil, err - } - } else { - _, err = forgefed.GetFederationHost(ctx, federatedUser.FederationHostID) - if err != nil { - return nil, err - } - } - - if federatedUser.PublicKey.Valid { - pubKey, err := x509.ParsePKIXPublicKey(federatedUser.PublicKey.V) - if err != nil { - return nil, err - } - return pubKey, nil - } - - // Fetch missing public key - pubKey, pubKeyBytes, apPerson, err := fetchKeyFromAp(ctx, *keyURL) - if err != nil { - return nil, err - } - if apPerson.Type == ap.ActivityVocabularyType("Person") { - // Check federatedUser.id = person.id - if federatedUser.ExternalID != apPerson.ID.String() { - return nil, fmt.Errorf("federated user fetched (%v) does not match the stored one %v", apPerson, federatedUser) - } - // update federated user - federatedUser.KeyID = sql.NullString{ - String: apPerson.PublicKey.ID.String(), - Valid: true, - } - federatedUser.PublicKey = sql.Null[sql.RawBytes]{ - V: pubKeyBytes, - Valid: true, - } - err = user.UpdateFederatedUser(ctx, federatedUser) - if err != nil { - return nil, err - } - return pubKey, nil - } - return nil, nil -} - -func FindOrCreateFederationHostKey(ctx *context_service.Base, keyID string) (pubKey any, err error) { - keyURL, err := url.Parse(keyID) - if err != nil { - return nil, err - } - rawActorID, err := NewActorIDFromKeyID(ctx, keyID) - if err != nil { - return nil, err - } - - // Is there an already known federation host? - federationHost, err := forgefed.FindFederationHostByKeyID(ctx, keyURL.String()) - if err != nil { - return nil, err - } - - if federationHost == nil { - federationHost, err = FindOrCreateFederationHost(ctx, rawActorID.AsURI()) - if err != nil { - return nil, err - } - } - - // Is there an already an key? - if federationHost.PublicKey.Valid { - pubKey, err := x509.ParsePKIXPublicKey(federationHost.PublicKey.V) - if err != nil { - return nil, err - } - return pubKey, nil - } - - // If not, fetch missing public key - pubKey, pubKeyBytes, apPerson, err := fetchKeyFromAp(ctx, *keyURL) - if err != nil { - return nil, err - } - if apPerson.Type == ap.ActivityVocabularyType("Application") { - // Check federationhost.id = person.id - if federationHost.HostPort != rawActorID.HostPort || federationHost.HostFqdn != rawActorID.Host || - federationHost.HostSchema != rawActorID.HostSchema { - return nil, fmt.Errorf("federation host fetched (%v) does not match the stored one %v", apPerson, federationHost) - } - // update federation host - federationHost.KeyID = sql.NullString{ - String: apPerson.PublicKey.ID.String(), - Valid: true, - } - federationHost.PublicKey = sql.Null[sql.RawBytes]{ - V: pubKeyBytes, - Valid: true, - } - err = forgefed.UpdateFederationHost(ctx, federationHost) - if err != nil { - return nil, err - } - return pubKey, nil - } - return nil, nil -} - -func fetchKeyFromAp(ctx *context_service.Base, keyURL url.URL) (pubKey any, pubKeyBytes []byte, apPerson *ap.Person, err error) { - actionsUser := user.NewAPServerActor() - clientFactory, err := activitypub.GetClientFactory(ctx) - if err != nil { - return nil, nil, nil, err - } - - apClient, err := clientFactory.WithKeys(ctx, actionsUser, actionsUser.KeyID()) - if err != nil { - return nil, nil, nil, err - } - - b, err := apClient.GetBody(keyURL.String()) - if err != nil { - return nil, nil, nil, err - } - - person := ap.PersonNew(ap.IRI(keyURL.String())) - err = person.UnmarshalJSON(b) - if err != nil { - return nil, nil, nil, fmt.Errorf("ActivityStreams type cannot be converted to one known to have publicKey property: %w", err) - } - - pubKeyFromAp := person.PublicKey - if pubKeyFromAp.ID.String() != keyURL.String() { - return nil, nil, nil, fmt.Errorf("cannot find publicKey with id: %v in %v", keyURL, string(b)) - } - - pubKeyBytes, err = decodePublicKeyPem(pubKeyFromAp.PublicKeyPem) - if err != nil { - return nil, nil, nil, err - } - - pubKey, err = x509.ParsePKIXPublicKey(pubKeyBytes) - if err != nil { - return nil, nil, nil, err - } - - return pubKey, pubKeyBytes, person, err -} - -func decodePublicKeyPem(pubKeyPem string) ([]byte, error) { - block, _ := pem.Decode([]byte(pubKeyPem)) - if block == nil || block.Type != "PUBLIC KEY" { - return nil, errors.New("could not decode publicKeyPem to PUBLIC KEY pem block type") - } - - return block.Bytes, nil -} diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 7033264f18..989f69d4f4 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -440,29 +440,11 @@ func getCommitFileLineCount(commit *git.Commit, filePath string) int { if err != nil { return 0 } - reader, err := blob.DataAsync() + lineCount, err := blob.GetBlobLineCount() if err != nil { return 0 } - defer reader.Close() - buf := make([]byte, 32*1024) - count := 1 - lineSep := []byte{'\n'} - - c, err := reader.Read(buf) - if c == 0 && err == io.EOF { - return 0 - } - for { - count += bytes.Count(buf[:c], lineSep) - switch { - case err == io.EOF: - return count - case err != nil: - return count - } - c, err = reader.Read(buf) - } + return lineCount } // Diff represents a difference between two git trees. @@ -1157,7 +1139,7 @@ func GetDiffSimple(ctx context.Context, gitRepo *git.Repository, opts *DiffOptio // so if we are using at least this version of git we don't have to tell ParsePatch to do // the skipping for us parsePatchSkipToFile := opts.SkipTo - if opts.SkipTo != "" { + if opts.SkipTo != "" && git.CheckGitVersionAtLeast("2.31") == nil { cmdDiff.AddOptionFormat("--skip-to=%s", opts.SkipTo) parsePatchSkipToFile = "" } diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index 695b177b8b..3d3c8432c4 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -712,8 +712,6 @@ func TestGetDiffFull(t *testing.T) { assert.Equal(t, ".gitattributes", diff.Files[0].Name) assert.Equal(t, "24139dae656713ba861751fb2c2ac38839349a7a", diff.Files[0].NameHash) - assert.Len(t, diff.Files[0].Sections, 2) - assert.Equal(t, 4, diff.Files[0].Sections[1].Lines[0].SectionInfo.LeftIdx) }) } diff --git a/services/mailer/mail_actions.go b/services/mailer/mail_actions.go index fa0d2635f1..09763e164e 100644 --- a/services/mailer/mail_actions.go +++ b/services/mailer/mail_actions.go @@ -16,8 +16,8 @@ const ( tplActionNowDone base.TplName = "actions/now_done" ) -var MailActionRun = mailActionRun // make it mockable -func mailActionRun(run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) error { +// requires !run.Status.IsSuccess() or !lastRun.Status.IsSuccess() +func MailActionRun(run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) error { if setting.MailService == nil { // No mail service configured return nil diff --git a/services/mailer/mail_actions_now_done_test.go b/services/mailer/mail_actions_now_done_test.go index f4c597c99c..6a01ea7631 100644 --- a/services/mailer/mail_actions_now_done_test.go +++ b/services/mailer/mail_actions_now_done_test.go @@ -57,91 +57,6 @@ func assertTranslatedLocaleMailActionsNowDone(t *testing.T, msgBody string) { AssertTranslatedLocale(t, msgBody, "mail.actions.successful_run_after_failure", "mail.actions.not_successful_run", "mail.actions.run_info_cur_status", "mail.actions.run_info_ref", "mail.actions.run_info_previous_status", "mail.actions.run_info_trigger", "mail.view_it_on") } -func TestActionRunNowDoneStatusMatrix(t *testing.T) { - successStatuses := []actions_model.Status{ - actions_model.StatusSuccess, - actions_model.StatusSkipped, - actions_model.StatusCancelled, - } - failureStatuses := []actions_model.Status{ - actions_model.StatusFailure, - } - - for _, testCase := range []struct { - name string - statuses []actions_model.Status - hasLastRun bool - lastStatuses []actions_model.Status - run bool - }{ - { - name: "FailureNoLastRun", - statuses: failureStatuses, - run: true, - }, - { - name: "SuccessNoLastRun", - statuses: successStatuses, - run: false, - }, - { - name: "FailureLastRunSuccess", - statuses: failureStatuses, - hasLastRun: true, - lastStatuses: successStatuses, - run: true, - }, - { - name: "FailureLastRunFailure", - statuses: failureStatuses, - hasLastRun: true, - lastStatuses: failureStatuses, - run: true, - }, - { - name: "SuccessLastRunFailure", - statuses: successStatuses, - hasLastRun: true, - lastStatuses: failureStatuses, - run: true, - }, - { - name: "SuccessLastRunSuccess", - statuses: successStatuses, - hasLastRun: true, - lastStatuses: successStatuses, - run: false, - }, - } { - t.Run(testCase.name, func(t *testing.T) { - var called bool - defer test.MockVariableValue(&MailActionRun, func(run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) error { - called = true - return nil - })() - for _, status := range testCase.statuses { - for _, lastStatus := range testCase.lastStatuses { - called = false - n := NewNotifier() - var lastRun *actions_model.ActionRun - if testCase.hasLastRun { - lastRun = &actions_model.ActionRun{ - Status: lastStatus, - } - } - n.ActionRunNowDone(t.Context(), - &actions_model.ActionRun{ - Status: status, - }, - actions_model.StatusUnknown, - lastRun) - assert.Equal(t, testCase.run, called, "status = %s, lastStatus = %s", status, lastStatus) - } - } - }) - } -} - func TestActionRunNowDoneNotificationMail(t *testing.T) { ctx := t.Context() diff --git a/services/mailer/mailer.go b/services/mailer/mailer.go index d8646d9ddd..ca5c645e0c 100644 --- a/services/mailer/mailer.go +++ b/services/mailer/mailer.go @@ -29,7 +29,7 @@ import ( notify_service "forgejo.org/services/notify" ntlmssp "github.com/Azure/go-ntlmssp" - "github.com/inbucket/html2text" + "github.com/jaytaylor/html2text" "gopkg.in/gomail.v2" ) diff --git a/services/mailer/notify.go b/services/mailer/notify.go index 640de31fcc..7461a67181 100644 --- a/services/mailer/notify.go +++ b/services/mailer/notify.go @@ -212,7 +212,7 @@ func (m *mailNotifier) NewUserSignUp(ctx context.Context, newUser *user_model.Us func (m *mailNotifier) ActionRunNowDone(ctx context.Context, run *actions_model.ActionRun, priorStatus actions_model.Status, lastRun *actions_model.ActionRun) { // Only send a mail on a successful run when the workflow recovered (i.e., the run before failed). - if !run.Status.IsFailure() && (lastRun == nil || !lastRun.Status.IsFailure()) { + if run.Status.IsSuccess() && (lastRun == nil || lastRun.Status.IsSuccess()) { return } if err := MailActionRun(run, priorStatus, lastRun); err != nil { diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 76ae0df018..1805ffc527 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -103,7 +103,11 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) remoteRepoName := "head_repo" baseBranch := "base" - fetchArgs := git.TrustedCmdArgs{"--no-tags", "--no-write-commit-graph"} + fetchArgs := git.TrustedCmdArgs{"--no-tags"} + if git.CheckGitVersionAtLeast("2.25.0") == nil { + // Writing the commit graph can be slow and is not needed here + fetchArgs = append(fetchArgs, "--no-write-commit-graph") + } // addCacheRepo adds git alternatives for the cacheRepoPath in the repoPath addCacheRepo := func(repoPath, cacheRepoPath string) error { diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 5a6006e9f2..3d2217df18 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -5,7 +5,6 @@ package files import ( "context" - "errors" "fmt" "net/url" "path" @@ -206,7 +205,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref } else if entry.IsLink() { contentsResponse.Type = string(ContentTypeLink) // The target of a symlink file is the content of the file - targetFromContent, err := entry.LinkTarget() + targetFromContent, err := entry.Blob().GetBlobContent(1024) if err != nil { return nil, err } @@ -274,11 +273,13 @@ func GetBlobBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git if err != nil { return nil, err } - content, err := gitBlob.GetContentBase64(setting.API.DefaultMaxBlobSize) - if err != nil && !errors.As(err, &git.BlobTooLargeError{}) { - return nil, err + content := "" + if gitBlob.Size() <= setting.API.DefaultMaxBlobSize { + content, err = gitBlob.GetBlobContentBase64() + if err != nil { + return nil, err + } } - return &api.GitBlob{ SHA: gitBlob.ID.String(), URL: repo.APIURL() + "/git/blobs/" + url.PathEscape(gitBlob.ID.String()), diff --git a/services/repository/files/file.go b/services/repository/files/file.go index 5b93258840..ef9a87dbcf 100644 --- a/services/repository/files/file.go +++ b/services/repository/files/file.go @@ -104,35 +104,36 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *user_m // then we use bogus User objects for them to store their FullName and Email. // If only one of the two are provided, we set both of them to it. // If neither are provided, both are the doer. - getUser := func(identity *IdentityOptions) *user_model.User { - if identity == nil || identity.Email == "" { - return nil - } - - if doer != nil && strings.EqualFold(doer.Email, identity.Email) { - user := doer // the committer is the doer, so will use their user object - if identity.Name != "" { - user.FullName = identity.Name + if committer != nil && committer.Email != "" { + if doer != nil && strings.EqualFold(doer.Email, committer.Email) { + committerUser = doer // the committer is the doer, so will use their user object + if committer.Name != "" { + committerUser.FullName = committer.Name } // Use the provided email and not revert to placeholder mail. - user.KeepEmailPrivate = false - return user - } - - var id int64 - if doer != nil { - id = doer.ID - } - return &user_model.User{ - ID: id, // Needed to ensure the doer is checked to pass rules for instance signing of CRUD actions. - FullName: identity.Name, - Email: identity.Email, + committerUser.KeepEmailPrivate = false + } else { + committerUser = &user_model.User{ + FullName: committer.Name, + Email: committer.Email, + } + } + } + if author != nil && author.Email != "" { + if doer != nil && strings.EqualFold(doer.Email, author.Email) { + authorUser = doer // the author is the doer, so will use their user object + if authorUser.Name != "" { + authorUser.FullName = author.Name + } + // Use the provided email and not revert to placeholder mail. + authorUser.KeepEmailPrivate = false + } else { + authorUser = &user_model.User{ + FullName: author.Name, + Email: author.Email, + } } } - - committerUser = getUser(committer) - authorUser = getUser(author) - if authorUser == nil { if committerUser != nil { authorUser = committerUser // No valid author was given so use the committer diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index 18b5226c02..5b1dd65b5a 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -147,7 +147,11 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user stdout := &strings.Builder{} stderr := &strings.Builder{} - cmdApply := git.NewCommand(ctx, "apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary", "-3") + cmdApply := git.NewCommand(ctx, "apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary") + if git.CheckGitVersionAtLeast("2.32") == nil { + cmdApply.AddArguments("-3") + } + if err := cmdApply.Run(&git.RunOpts{ Dir: t.basePath, Stdout: stdout, diff --git a/services/webhook/discord.go b/services/webhook/discord.go index 7259c4a995..db98d40583 100644 --- a/services/webhook/discord.go +++ b/services/webhook/discord.go @@ -350,7 +350,7 @@ func parseHookPullRequestEventType(event webhook_module.HookEventType) (string, case webhook_module.HookEventPullRequestReviewApproved: return "approved", nil case webhook_module.HookEventPullRequestReviewRejected: - return "requested changes", nil + return "rejected", nil case webhook_module.HookEventPullRequestReviewComment: return "comment", nil default: diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl index 6d2f441793..8646562ca8 100644 --- a/templates/repo/issue/card.tmpl +++ b/templates/repo/issue/card.tmpl @@ -4,7 +4,7 @@ {{if $attachments}}
{{range $attachments}} - {{.Name}} + {{.Name}} {{end}}
{{end}} diff --git a/templates/repo/issue/view_content/attachments.tmpl b/templates/repo/issue/view_content/attachments.tmpl index 8b5094771a..79085df3ab 100644 --- a/templates/repo/issue/view_content/attachments.tmpl +++ b/templates/repo/issue/view_content/attachments.tmpl @@ -31,7 +31,7 @@ {{if FilenameIsImage .Name}} {{if not (StringUtils.Contains (StringUtils.ToString $.RenderedContent) .UUID)}} - {{.Name}} + {{.Name}} {{end}} {{end}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 3bc4cd0773..2e9ba3dcd7 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -634,7 +634,7 @@
- + {{svg "octicon-x" 16}} diff --git a/templates/repo/release/new.tmpl b/templates/repo/release/new.tmpl index c5c7eb23fa..788d7f015c 100644 --- a/templates/repo/release/new.tmpl +++ b/templates/repo/release/new.tmpl @@ -46,7 +46,7 @@
- +
{{template "shared/combomarkdowneditor" (dict diff --git a/templates/repo/settings/navbar.tmpl b/templates/repo/settings/navbar.tmpl index 6e9f396e2e..0f6cb74d8c 100644 --- a/templates/repo/settings/navbar.tmpl +++ b/templates/repo/settings/navbar.tmpl @@ -7,7 +7,7 @@
{{ctx.Locale.Tr "repo.settings.units.units"}}