diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 95d673cd309..0bf0edc45ee 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,10 @@ { "name": "Gitea DevContainer", "image": "mcr.microsoft.com/devcontainers/go:1.24-bookworm", + "containerEnv": { + // override "local" from packaged version + "GOTOOLCHAIN": "auto" + }, "features": { // installs nodejs into container "ghcr.io/devcontainers/features/node:1": { diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index c2cc14f771c..5919a1616ac 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -75,11 +75,6 @@ jobs: - name: Get cleaned branch name id: clean_name run: | - # if main then say nightly otherwise cleanup name - if [ "${{ github.ref }}" = "refs/heads/main" ]; then - echo "branch=nightly" >> "$GITHUB_OUTPUT" - exit 0 - fi REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//') echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT" - name: Login to Docker Hub @@ -122,11 +117,6 @@ jobs: - name: Get cleaned branch name id: clean_name run: | - # if main then say nightly otherwise cleanup name - if [ "${{ github.ref }}" = "refs/heads/main" ]; then - echo "branch=nightly" >> "$GITHUB_OUTPUT" - exit 0 - fi REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//') echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT" - name: Login to Docker Hub diff --git a/Dockerfile b/Dockerfile index f852cf42355..014eed9d467 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build stage -FROM docker.io/library/golang:1.24-alpine3.22 AS build-env +FROM docker.io/library/golang:1.25-alpine3.22 AS build-env ARG GOPROXY ENV GOPROXY=${GOPROXY:-direct} diff --git a/Dockerfile.rootless b/Dockerfile.rootless index f955edc6678..677d36bbcc0 100644 --- a/Dockerfile.rootless +++ b/Dockerfile.rootless @@ -1,5 +1,5 @@ # Build stage -FROM docker.io/library/golang:1.24-alpine3.22 AS build-env +FROM docker.io/library/golang:1.25-alpine3.22 AS build-env ARG GOPROXY ENV GOPROXY=${GOPROXY:-direct} diff --git a/MAINTAINERS b/MAINTAINERS index 7643ab000fe..63da471f9b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -36,9 +36,7 @@ a1012112796 <1012112796@qq.com> (@a1012112796) Karl Heinz Marbaise (@khmarbaise) Norwin Roosen (@noerw) Kyle Dumont (@kdumontnu) -Patrick Schratz (@pat-s) Janis Estelmann (@KN4CK3R) -Steven Kriegler (@justusbunsi) Jimmy Praet (@jpraet) Leon Hofmeister (@delvh) Wim (@42wim) diff --git a/Makefile b/Makefile index 3aabd55a72f..9cd32e4c33f 100644 --- a/Makefile +++ b/Makefile @@ -23,12 +23,12 @@ SHASUM ?= shasum -a 256 HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes) COMMA := , -XGO_VERSION := go-1.24.x +XGO_VERSION := go-1.25.x AIR_PACKAGE ?= github.com/air-verse/air@v1 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0 -GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.4.0 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.12 MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.7.0 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.32.3 @@ -48,6 +48,17 @@ ifeq ($(HAS_GO), yes) CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS) endif +CGO_ENABLED ?= 0 +ifneq (,$(findstring sqlite,$(TAGS))$(findstring pam,$(TAGS))) + CGO_ENABLED = 1 +endif + +STATIC ?= +EXTLDFLAGS ?= +ifneq ($(STATIC),) + EXTLDFLAGS = -extldflags "-static" +endif + ifeq ($(GOOS),windows) IS_WINDOWS := yes else ifeq ($(patsubst Windows%,Windows,$(OS)),Windows) @@ -746,7 +757,10 @@ security-check: go run $(GOVULNCHECK_PACKAGE) -show color ./... $(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ) - CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@ +ifneq ($(and $(STATIC),$(findstring pam,$(TAGS))),) + $(error pam support set via TAGS doesn't support static builds) +endif + CGO_ENABLED="$(CGO_ENABLED)" CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(EXTLDFLAGS) $(LDFLAGS)' -o $@ .PHONY: release release: frontend generate release-windows release-linux release-darwin release-freebsd release-copy release-compress vendor release-sources release-check diff --git a/cmd/admin.go b/cmd/admin.go index 559544edd33..5c58a40ca27 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -100,7 +100,7 @@ func runRepoSyncReleases(ctx context.Context, _ *cli.Command) error { return err } - if err := git.InitSimple(ctx); err != nil { + if err := git.InitSimple(); err != nil { return err } diff --git a/cmd/admin_user_change_password_test.go b/cmd/admin_user_change_password_test.go index 17d0382af74..902632f3e49 100644 --- a/cmd/admin_user_change_password_test.go +++ b/cmd/admin_user_change_password_test.go @@ -18,12 +18,12 @@ func TestChangePasswordCommand(t *testing.T) { ctx := t.Context() defer func() { - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.User{})) }() t.Run("change password successfully", func(t *testing.T) { // defer func() { - // require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{})) + // require.NoError(t, db.TruncateBeans(t.Context(), &user_model.User{})) // }() // Prepare test user unittest.AssertNotExistsBean(t, &user_model.User{LowerName: "testuser"}) diff --git a/cmd/admin_user_create_test.go b/cmd/admin_user_create_test.go index 437e07d9a28..dbe949ff8d2 100644 --- a/cmd/admin_user_create_test.go +++ b/cmd/admin_user_create_test.go @@ -19,9 +19,9 @@ import ( func TestAdminUserCreate(t *testing.T) { reset := func() { - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{})) - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{})) - require.NoError(t, db.TruncateBeans(db.DefaultContext, &auth_model.AccessToken{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.User{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.EmailAddress{})) + require.NoError(t, db.TruncateBeans(t.Context(), &auth_model.AccessToken{})) } t.Run("MustChangePassword", func(t *testing.T) { diff --git a/cmd/admin_user_delete_test.go b/cmd/admin_user_delete_test.go index d0330582d77..b68b358152a 100644 --- a/cmd/admin_user_delete_test.go +++ b/cmd/admin_user_delete_test.go @@ -19,9 +19,9 @@ import ( func TestAdminUserDelete(t *testing.T) { ctx := t.Context() defer func() { - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{})) - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{})) - require.NoError(t, db.TruncateBeans(db.DefaultContext, &auth_model.AccessToken{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.User{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.EmailAddress{})) + require.NoError(t, db.TruncateBeans(t.Context(), &auth_model.AccessToken{})) }() setupTestUser := func(t *testing.T) { @@ -104,8 +104,8 @@ func TestAdminUserDeleteFailure(t *testing.T) { require.Contains(t, err.Error(), tc.expectedErr) }) - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{})) - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{})) - require.NoError(t, db.TruncateBeans(db.DefaultContext, &auth_model.AccessToken{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.User{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.EmailAddress{})) + require.NoError(t, db.TruncateBeans(t.Context(), &auth_model.AccessToken{})) } } diff --git a/cmd/admin_user_must_change_password_test.go b/cmd/admin_user_must_change_password_test.go index a6611fdc041..efdbe3a9ee9 100644 --- a/cmd/admin_user_must_change_password_test.go +++ b/cmd/admin_user_must_change_password_test.go @@ -16,7 +16,7 @@ import ( func TestMustChangePassword(t *testing.T) { defer func() { - require.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{})) + require.NoError(t, db.TruncateBeans(t.Context(), &user_model.User{})) }() err := microcmdUserCreate().Run(t.Context(), []string{"create", "--username", "testuser", "--email", "testuser@gitea.local", "--random-password"}) require.NoError(t, err) diff --git a/cmd/doctor.go b/cmd/doctor.go index 9e0fcbf8779..596dd611786 100644 --- a/cmd/doctor.go +++ b/cmd/doctor.go @@ -128,7 +128,7 @@ func runRecreateTable(ctx context.Context, cmd *cli.Command) error { } recreateTables := migrate_base.RecreateTables(beans...) - return db.InitEngineWithMigration(ctx, func(ctx context.Context, x *xorm.Engine) error { + return db.InitEngineWithMigration(context.Background(), func(ctx context.Context, x *xorm.Engine) error { if err := migrations.EnsureUpToDate(ctx, x); err != nil { return err } diff --git a/cmd/dump_repo.go b/cmd/dump_repo.go index a75b2d1b94f..beda305c85f 100644 --- a/cmd/dump_repo.go +++ b/cmd/dump_repo.go @@ -90,7 +90,7 @@ func runDumpRepository(ctx context.Context, cmd *cli.Command) error { } // migrations.GiteaLocalUploader depends on git module - if err := git.InitSimple(context.Background()); err != nil { + if err := git.InitSimple(); err != nil { return err } @@ -179,7 +179,7 @@ func runDumpRepository(ctx context.Context, cmd *cli.Command) error { } if err := migrations.DumpRepository( - context.Background(), + ctx, repoDir, cmd.String("owner_name"), opts, diff --git a/cmd/migrate_storage_test.go b/cmd/migrate_storage_test.go index 6817867e288..3ea193eb1ea 100644 --- a/cmd/migrate_storage_test.go +++ b/cmd/migrate_storage_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -30,7 +29,7 @@ func TestMigratePackages(t *testing.T) { assert.NoError(t, err) defer buf.Close() - v, f, err := packages_service.CreatePackageAndAddFile(db.DefaultContext, &packages_service.PackageCreationInfo{ + v, f, err := packages_service.CreatePackageAndAddFile(t.Context(), &packages_service.PackageCreationInfo{ PackageInfo: packages_service.PackageInfo{ Owner: creator, PackageType: packages.TypeGeneric, diff --git a/cmd/serv.go b/cmd/serv.go index 38c79f68cd2..089d0e3bb7c 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -65,7 +65,7 @@ func setup(ctx context.Context, debug bool) { _ = fail(ctx, "Unable to access repository path", "Unable to access repository path %q, err: %v", setting.RepoRootPath, err) return } - if err := git.InitSimple(context.Background()); err != nil { + if err := git.InitSimple(); err != nil { _ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err) } } diff --git a/cmd/web.go b/cmd/web.go index 61ee3cbc203..4723ddbbdd2 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -236,15 +236,16 @@ func serveInstalled(c *cli.Command) error { } func servePprof() { + // FIXME: it shouldn't use the global DefaultServeMux, and it should use a proper context http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler()) - _, _, finished := process.GetManager().AddTypedContext(context.Background(), "Web: PProf Server", process.SystemProcessType, true) - // The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment it's not worth to introduce a configurable option for it. + _, _, finished := process.GetManager().AddTypedContext(context.TODO(), "Web: PProf Server", process.SystemProcessType, true) + // The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment, it's not worth introducing a configurable option for it. log.Info("Starting pprof server on localhost:6060") log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", nil)) finished() } -func runWeb(_ context.Context, cmd *cli.Command) error { +func runWeb(ctx context.Context, cmd *cli.Command) error { defer func() { if panicked := recover(); panicked != nil { log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2)) @@ -255,7 +256,7 @@ func runWeb(_ context.Context, cmd *cli.Command) error { return fmt.Errorf("unknown command: %s", subCmdName) } - managerCtx, cancel := context.WithCancel(context.Background()) + managerCtx, cancel := context.WithCancel(ctx) graceful.InitManager(managerCtx) defer cancel() diff --git a/contrib/upgrade.sh b/contrib/upgrade.sh index 4b166a02a0d..e5e296ea8b2 100755 --- a/contrib/upgrade.sh +++ b/contrib/upgrade.sh @@ -85,7 +85,7 @@ fi # confirm update echo "Checking currently installed version..." current=$(giteacmd --version | cut -d ' ' -f 3) -[[ "$current" == "$giteaversion" ]] && echo "$current is already installed, stopping." && exit 1 +[[ "$current" == "$giteaversion" ]] && echo "$current is already installed, stopping." && exit 0 if [[ -z "${no_confirm:-}" ]]; then echo "Make sure to read the changelog first: https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md" echo "Are you ready to update Gitea from ${current} to ${giteaversion}? (y/N)" diff --git a/flake.lock b/flake.lock index 67f87dfaf62..16a487ba133 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1752480373, - "narHash": "sha256-JHQbm+OcGp32wAsXTE/FLYGNpb+4GLi5oTvCxwSoBOA=", + "lastModified": 1755186698, + "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "62e0f05ede1da0d54515d4ea8ce9c733f12d9f08", + "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index e3375b82b35..9008e1f8391 100644 --- a/flake.nix +++ b/flake.nix @@ -11,33 +11,58 @@ pkgs = nixpkgs.legacyPackages.${system}; in { - devShells.default = pkgs.mkShell { - buildInputs = with pkgs; [ - # generic - git - git-lfs - gnumake - gnused - gnutar - gzip + devShells.default = + with pkgs; + let + # only bump toolchain versions here + go = go_1_25; + nodejs = nodejs_24; + python3 = python312; - # frontend - nodejs_22 + # Platform-specific dependencies + linuxOnlyInputs = lib.optionals pkgs.stdenv.isLinux [ + glibc.static + ]; - # linting - python312 - uv + linuxOnlyEnv = lib.optionalAttrs pkgs.stdenv.isLinux { + CFLAGS = "-I${glibc.static.dev}/include"; + LDFLAGS = "-L ${glibc.static}/lib"; + }; + in + pkgs.mkShell ( + { + buildInputs = [ + # generic + git + git-lfs + gnumake + gnused + gnutar + gzip + zip - # backend - go_1_24 - gofumpt - sqlite - ]; - shellHook = '' - export GO="${pkgs.go_1_24}/bin/go" - export GOROOT="${pkgs.go_1_24}/share/go" - ''; - }; + # frontend + nodejs + + # linting + python3 + uv + + # backend + go + gofumpt + sqlite + ] + ++ linuxOnlyInputs; + + GO = "${go}/bin/go"; + GOROOT = "${go}/share/go"; + + TAGS = "sqlite sqlite_unlock_notify"; + STATIC = "true"; + } + // linuxOnlyEnv + ); } ); } diff --git a/go.mod b/go.mod index eab0d417cfb..03fc2ae4bfe 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module code.gitea.io/gitea -go 1.24.5 +go 1.24.6 // rfc5280 said: "The serial number is an integer assigned by the CA to each certificate." // But some CAs use negative serial number, just relax the check. related: @@ -27,7 +27,7 @@ require ( github.com/ProtonMail/go-crypto v1.2.0 github.com/PuerkitoBio/goquery v1.10.3 github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3 - github.com/alecthomas/chroma/v2 v2.17.0 + github.com/alecthomas/chroma/v2 v2.20.0 github.com/aws/aws-sdk-go-v2/credentials v1.17.67 github.com/aws/aws-sdk-go-v2/service/codecommit v1.28.2 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb diff --git a/go.sum b/go.sum index 2ccdc64d776..b912466eb09 100644 --- a/go.sum +++ b/go.sum @@ -78,11 +78,11 @@ github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3/go.mod h1:hMNtySovKkn2 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.17.0 h1:3r2Cgk+nXNICMBxIFGnTRTbQFUwMiLisW+9uos0TtUI= -github.com/alecthomas/chroma/v2 v2.17.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= 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= +github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= +github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI= github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58PaB6aA= diff --git a/models/actions/runner_token_test.go b/models/actions/runner_token_test.go index 21614b70862..243d6716a00 100644 --- a/models/actions/runner_token_test.go +++ b/models/actions/runner_token_test.go @@ -6,7 +6,6 @@ package actions import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" @@ -15,16 +14,16 @@ import ( func TestGetLatestRunnerToken(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3}) - expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0) + expectedToken, err := GetLatestRunnerToken(t.Context(), 1, 0) assert.NoError(t, err) assert.Equal(t, expectedToken, token) } func TestNewRunnerToken(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - token, err := NewRunnerToken(db.DefaultContext, 1, 0) + token, err := NewRunnerToken(t.Context(), 1, 0) assert.NoError(t, err) - expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0) + expectedToken, err := GetLatestRunnerToken(t.Context(), 1, 0) assert.NoError(t, err) assert.Equal(t, expectedToken, token) } @@ -33,8 +32,8 @@ func TestUpdateRunnerToken(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3}) token.IsActive = true - assert.NoError(t, UpdateRunnerToken(db.DefaultContext, token)) - expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0) + assert.NoError(t, UpdateRunnerToken(t.Context(), token)) + expectedToken, err := GetLatestRunnerToken(t.Context(), 1, 0) assert.NoError(t, err) assert.Equal(t, expectedToken, token) } diff --git a/models/activities/action.go b/models/activities/action.go index 1a0dfe64126..8e589eda88d 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -320,7 +320,7 @@ func (a *Action) GetCommentHTMLURL(ctx context.Context) string { return "#" } - return a.Issue.HTMLURL() + return a.Issue.HTMLURL(ctx) } // GetCommentLink returns link to action comment. diff --git a/models/activities/action_test.go b/models/activities/action_test.go index ff311ac8918..9447f39d62a 100644 --- a/models/activities/action_test.go +++ b/models/activities/action_test.go @@ -25,7 +25,7 @@ func TestAction_GetRepoPath(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) action := &activities_model.Action{RepoID: repo.ID} - assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath(db.DefaultContext)) + assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath(t.Context())) } func TestAction_GetRepoLink(t *testing.T) { @@ -37,9 +37,9 @@ func TestAction_GetRepoLink(t *testing.T) { defer test.MockVariableValue(&setting.AppURL, "https://try.gitea.io/suburl/")() defer test.MockVariableValue(&setting.AppSubURL, "/suburl")() expected := path.Join(setting.AppSubURL, owner.Name, repo.Name) - assert.Equal(t, expected, action.GetRepoLink(db.DefaultContext)) - assert.Equal(t, repo.HTMLURL(), action.GetRepoAbsoluteLink(db.DefaultContext)) - assert.Equal(t, comment.HTMLURL(db.DefaultContext), action.GetCommentHTMLURL(db.DefaultContext)) + assert.Equal(t, expected, action.GetRepoLink(t.Context())) + assert.Equal(t, repo.HTMLURL(), action.GetRepoAbsoluteLink(t.Context())) + assert.Equal(t, comment.HTMLURL(t.Context()), action.GetCommentHTMLURL(t.Context())) } func TestActivityReadable(t *testing.T) { @@ -91,37 +91,37 @@ func TestConsistencyUpdateAction(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &activities_model.Action{ ID: int64(id), }) - _, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = '' WHERE id = ?`, id) + _, err := db.GetEngine(t.Context()).Exec(`UPDATE action SET created_unix = '' WHERE id = ?`, id) assert.NoError(t, err) actions := make([]*activities_model.Action, 0, 1) // // XORM returns an error when created_unix is a string // - err = db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions) + err = db.GetEngine(t.Context()).Where("id = ?", id).Find(&actions) if assert.Error(t, err) { assert.Contains(t, err.Error(), "type string to a int64: invalid syntax") } // // Get rid of incorrectly set created_unix // - count, err := activities_model.CountActionCreatedUnixString(db.DefaultContext) + count, err := activities_model.CountActionCreatedUnixString(t.Context()) assert.NoError(t, err) assert.EqualValues(t, 1, count) - count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) + count, err = activities_model.FixActionCreatedUnixString(t.Context()) assert.NoError(t, err) assert.EqualValues(t, 1, count) - count, err = activities_model.CountActionCreatedUnixString(db.DefaultContext) + count, err = activities_model.CountActionCreatedUnixString(t.Context()) assert.NoError(t, err) assert.EqualValues(t, 0, count) - count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) + count, err = activities_model.FixActionCreatedUnixString(t.Context()) assert.NoError(t, err) assert.EqualValues(t, 0, count) // // XORM must be happy now // - assert.NoError(t, db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions)) + assert.NoError(t, db.GetEngine(t.Context()).Where("id = ?", id).Find(&actions)) unittest.CheckConsistencyFor(t, &activities_model.Action{}) } @@ -133,19 +133,19 @@ func TestDeleteIssueActions(t *testing.T) { assert.NotEqual(t, issue.ID, issue.Index) // it needs to use different ID/Index to test the DeleteIssueActions to delete some actions by IssueIndex // insert a comment - err := db.Insert(db.DefaultContext, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID}) + err := db.Insert(t.Context(), &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID}) assert.NoError(t, err) comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID}) // truncate action table and insert some actions - err = db.TruncateBeans(db.DefaultContext, &activities_model.Action{}) + err = db.TruncateBeans(t.Context(), &activities_model.Action{}) assert.NoError(t, err) - err = db.Insert(db.DefaultContext, &activities_model.Action{ + err = db.Insert(t.Context(), &activities_model.Action{ OpType: activities_model.ActionCommentIssue, CommentID: comment.ID, }) assert.NoError(t, err) - err = db.Insert(db.DefaultContext, &activities_model.Action{ + err = db.Insert(t.Context(), &activities_model.Action{ OpType: activities_model.ActionCreateIssue, RepoID: issue.RepoID, Content: fmt.Sprintf("%d|content...", issue.Index), @@ -154,6 +154,6 @@ func TestDeleteIssueActions(t *testing.T) { // assert that the actions exist, then delete them unittest.AssertCount(t, &activities_model.Action{}, 2) - assert.NoError(t, activities_model.DeleteIssueActions(db.DefaultContext, issue.RepoID, issue.ID, issue.Index)) + assert.NoError(t, activities_model.DeleteIssueActions(t.Context(), issue.RepoID, issue.ID, issue.Index)) unittest.AssertCount(t, &activities_model.Action{}, 0) } diff --git a/models/activities/notification.go b/models/activities/notification.go index 6dde26fd53e..b482e6020af 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -280,11 +280,11 @@ func (n *Notification) HTMLURL(ctx context.Context) string { if n.Comment != nil { return n.Comment.HTMLURL(ctx) } - return n.Issue.HTMLURL() + return n.Issue.HTMLURL(ctx) case NotificationSourceCommit: - return n.Repository.HTMLURL() + "/commit/" + url.PathEscape(n.CommitID) + return n.Repository.HTMLURL(ctx) + "/commit/" + url.PathEscape(n.CommitID) case NotificationSourceRepository: - return n.Repository.HTMLURL() + return n.Repository.HTMLURL(ctx) } return "" } diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index 5d2a29bc366..6f2253c815d 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -20,7 +20,7 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) - assert.NoError(t, activities_model.CreateOrUpdateIssueNotifications(db.DefaultContext, issue.ID, 0, 2, 0)) + assert.NoError(t, activities_model.CreateOrUpdateIssueNotifications(t.Context(), issue.ID, 0, 2, 0)) // User 9 is inactive, thus notifications for user 1 and 4 are created notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: 1, IssueID: issue.ID}) @@ -34,7 +34,7 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { func TestNotificationsForUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - notfs, err := db.Find[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + notfs, err := db.Find[activities_model.Notification](t.Context(), activities_model.FindNotificationOptions{ UserID: user.ID, Status: []activities_model.NotificationStatus{ activities_model.NotificationStatusRead, @@ -55,7 +55,7 @@ func TestNotificationsForUser(t *testing.T) { func TestNotification_GetRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) - repo, err := notf.GetRepo(db.DefaultContext) + repo, err := notf.GetRepo(t.Context()) assert.NoError(t, err) assert.Equal(t, repo, notf.Repository) assert.Equal(t, notf.RepoID, repo.ID) @@ -64,7 +64,7 @@ func TestNotification_GetRepo(t *testing.T) { func TestNotification_GetIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) - issue, err := notf.GetIssue(db.DefaultContext) + issue, err := notf.GetIssue(t.Context()) assert.NoError(t, err) assert.Equal(t, issue, notf.Issue) assert.Equal(t, notf.IssueID, issue.ID) @@ -73,7 +73,7 @@ func TestNotification_GetIssue(t *testing.T) { func TestGetNotificationCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - cnt, err := db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + cnt, err := db.Count[activities_model.Notification](t.Context(), activities_model.FindNotificationOptions{ UserID: user.ID, Status: []activities_model.NotificationStatus{ activities_model.NotificationStatusRead, @@ -82,7 +82,7 @@ func TestGetNotificationCount(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 0, cnt) - cnt, err = db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{ + cnt, err = db.Count[activities_model.Notification](t.Context(), activities_model.FindNotificationOptions{ UserID: user.ID, Status: []activities_model.NotificationStatus{ activities_model.NotificationStatusUnread, @@ -97,14 +97,14 @@ func TestSetNotificationStatus(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead}) - _, err := activities_model.SetNotificationStatus(db.DefaultContext, notf.ID, user, activities_model.NotificationStatusPinned) + _, err := activities_model.SetNotificationStatus(t.Context(), notf.ID, user, activities_model.NotificationStatusPinned) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: notf.ID, Status: activities_model.NotificationStatusPinned}) - _, err = activities_model.SetNotificationStatus(db.DefaultContext, 1, user, activities_model.NotificationStatusRead) + _, err = activities_model.SetNotificationStatus(t.Context(), 1, user, activities_model.NotificationStatusRead) assert.Error(t, err) - _, err = activities_model.SetNotificationStatus(db.DefaultContext, unittest.NonexistentID, user, activities_model.NotificationStatusRead) + _, err = activities_model.SetNotificationStatus(t.Context(), unittest.NonexistentID, user, activities_model.NotificationStatusRead) assert.Error(t, err) } @@ -117,7 +117,7 @@ func TestUpdateNotificationStatuses(t *testing.T) { &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead}) notfPinned := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusPinned}) - assert.NoError(t, activities_model.UpdateNotificationStatuses(db.DefaultContext, user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead)) + assert.NoError(t, activities_model.UpdateNotificationStatuses(t.Context(), user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead)) unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{ID: notfUnread.ID, Status: activities_model.NotificationStatusRead}) unittest.AssertExistsAndLoadBean(t, @@ -130,11 +130,11 @@ func TestSetIssueReadBy(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) - assert.NoError(t, db.WithTx(db.DefaultContext, func(ctx context.Context) error { + assert.NoError(t, db.WithTx(t.Context(), func(ctx context.Context) error { return activities_model.SetIssueReadBy(ctx, issue.ID, user.ID) })) - nt, err := activities_model.GetIssueNotification(db.DefaultContext, user.ID, issue.ID) + nt, err := activities_model.GetIssueNotification(t.Context(), user.ID, issue.ID) assert.NoError(t, err) assert.Equal(t, activities_model.NotificationStatusRead, nt.Status) } diff --git a/models/activities/user_heatmap_test.go b/models/activities/user_heatmap_test.go index 380045d3c5d..66087325b1d 100644 --- a/models/activities/user_heatmap_test.go +++ b/models/activities/user_heatmap_test.go @@ -8,7 +8,6 @@ import ( "time" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/json" @@ -70,7 +69,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) { } // get the action for comparison - actions, count, err := activities_model.GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err := activities_model.GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedUser: user, Actor: doer, IncludePrivate: true, @@ -80,7 +79,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) { assert.NoError(t, err) // Get the heatmap and compare - heatmap, err := activities_model.GetUserHeatmapDataByUser(db.DefaultContext, user, doer) + heatmap, err := activities_model.GetUserHeatmapDataByUser(t.Context(), user, doer) var contributions int for _, hm := range heatmap { contributions += int(hm.Contributions) diff --git a/models/asymkey/gpg_key_test.go b/models/asymkey/gpg_key_test.go index 408cf157636..4621337f11b 100644 --- a/models/asymkey/gpg_key_test.go +++ b/models/asymkey/gpg_key_test.go @@ -232,7 +232,7 @@ Q0KHb+QcycSgbDx0ZAvdIacuKvBBcbxrsmFUI4LR+oIup0G9gUc0roPvr014jYQL =zHo9 -----END PGP PUBLIC KEY BLOCK-----` - keys, err := AddGPGKey(db.DefaultContext, 1, testEmailWithUpperCaseLetters, "", "") + keys, err := AddGPGKey(t.Context(), 1, testEmailWithUpperCaseLetters, "", "") assert.NoError(t, err) if assert.NotEmpty(t, keys) { key := keys[0] @@ -407,12 +407,12 @@ func TestTryGetKeyIDFromSignature(t *testing.T) { func TestParseGPGKey(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.NoError(t, db.Insert(db.DefaultContext, &user_model.EmailAddress{UID: 1, Email: "email1@example.com", IsActivated: true})) + assert.NoError(t, db.Insert(t.Context(), &user_model.EmailAddress{UID: 1, Email: "email1@example.com", IsActivated: true})) // create a key for test email e, err := openpgp.NewEntity("name", "comment", "email1@example.com", nil) require.NoError(t, err) - k, err := parseGPGKey(db.DefaultContext, 1, e, true) + k, err := parseGPGKey(t.Context(), 1, e, true) require.NoError(t, err) assert.NotEmpty(t, k.KeyID) assert.NotEmpty(t, k.Emails) // the key is valid, matches the email @@ -421,7 +421,7 @@ func TestParseGPGKey(t *testing.T) { for _, id := range e.Identities { id.Revocations = append(id.Revocations, &packet.Signature{RevocationReason: util.ToPointer(packet.KeyCompromised)}) } - k, err = parseGPGKey(db.DefaultContext, 1, e, true) + k, err = parseGPGKey(t.Context(), 1, e, true) require.NoError(t, err) assert.NotEmpty(t, k.KeyID) assert.Empty(t, k.Emails) // the key is revoked, matches no email diff --git a/models/asymkey/ssh_key_test.go b/models/asymkey/ssh_key_test.go index 21e4ddf62ec..d7f48ada033 100644 --- a/models/asymkey/ssh_key_test.go +++ b/models/asymkey/ssh_key_test.go @@ -12,7 +12,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" @@ -476,7 +475,7 @@ func runErr(t *testing.T, stdin []byte, args ...string) { func Test_PublicKeysAreExternallyManaged(t *testing.T) { key1 := unittest.AssertExistsAndLoadBean(t, &PublicKey{ID: 1}) - externals, err := PublicKeysAreExternallyManaged(db.DefaultContext, []*PublicKey{key1}) + externals, err := PublicKeysAreExternallyManaged(t.Context(), []*PublicKey{key1}) assert.NoError(t, err) assert.Len(t, externals, 1) assert.False(t, externals[0]) diff --git a/models/auth/access_token_test.go b/models/auth/access_token_test.go index 4360f1a2143..9ae072cc5fa 100644 --- a/models/auth/access_token_test.go +++ b/models/auth/access_token_test.go @@ -19,7 +19,7 @@ func TestNewAccessToken(t *testing.T) { UID: 3, Name: "Token C", } - assert.NoError(t, auth_model.NewAccessToken(db.DefaultContext, token)) + assert.NoError(t, auth_model.NewAccessToken(t.Context(), token)) unittest.AssertExistsAndLoadBean(t, token) invalidToken := &auth_model.AccessToken{ @@ -27,7 +27,7 @@ func TestNewAccessToken(t *testing.T) { UID: 2, Name: "Token F", } - assert.Error(t, auth_model.NewAccessToken(db.DefaultContext, invalidToken)) + assert.Error(t, auth_model.NewAccessToken(t.Context(), invalidToken)) } func TestAccessTokenByNameExists(t *testing.T) { @@ -40,16 +40,16 @@ func TestAccessTokenByNameExists(t *testing.T) { } // Check to make sure it doesn't exists already - exist, err := auth_model.AccessTokenByNameExists(db.DefaultContext, token) + exist, err := auth_model.AccessTokenByNameExists(t.Context(), token) assert.NoError(t, err) assert.False(t, exist) // Save it to the database - assert.NoError(t, auth_model.NewAccessToken(db.DefaultContext, token)) + assert.NoError(t, auth_model.NewAccessToken(t.Context(), token)) unittest.AssertExistsAndLoadBean(t, token) // This token must be found by name in the DB now - exist, err = auth_model.AccessTokenByNameExists(db.DefaultContext, token) + exist, err = auth_model.AccessTokenByNameExists(t.Context(), token) assert.NoError(t, err) assert.True(t, exist) @@ -60,32 +60,32 @@ func TestAccessTokenByNameExists(t *testing.T) { // Name matches but different user ID, this shouldn't exists in the // database - exist, err = auth_model.AccessTokenByNameExists(db.DefaultContext, user4Token) + exist, err = auth_model.AccessTokenByNameExists(t.Context(), user4Token) assert.NoError(t, err) assert.False(t, exist) } func TestGetAccessTokenBySHA(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "d2c6c1ba3890b309189a8e618c72a162e4efbf36") + token, err := auth_model.GetAccessTokenBySHA(t.Context(), "d2c6c1ba3890b309189a8e618c72a162e4efbf36") assert.NoError(t, err) assert.Equal(t, int64(1), token.UID) assert.Equal(t, "Token A", token.Name) assert.Equal(t, "2b3668e11cb82d3af8c6e4524fc7841297668f5008d1626f0ad3417e9fa39af84c268248b78c481daa7e5dc437784003494f", token.TokenHash) assert.Equal(t, "e4efbf36", token.TokenLastEight) - _, err = auth_model.GetAccessTokenBySHA(db.DefaultContext, "notahash") + _, err = auth_model.GetAccessTokenBySHA(t.Context(), "notahash") assert.Error(t, err) assert.True(t, auth_model.IsErrAccessTokenNotExist(err)) - _, err = auth_model.GetAccessTokenBySHA(db.DefaultContext, "") + _, err = auth_model.GetAccessTokenBySHA(t.Context(), "") assert.Error(t, err) assert.True(t, auth_model.IsErrAccessTokenEmpty(err)) } func TestListAccessTokens(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - tokens, err := db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1}) + tokens, err := db.Find[auth_model.AccessToken](t.Context(), auth_model.ListAccessTokensOptions{UserID: 1}) assert.NoError(t, err) if assert.Len(t, tokens, 2) { assert.Equal(t, int64(1), tokens[0].UID) @@ -94,39 +94,39 @@ func TestListAccessTokens(t *testing.T) { assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B") } - tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2}) + tokens, err = db.Find[auth_model.AccessToken](t.Context(), auth_model.ListAccessTokensOptions{UserID: 2}) assert.NoError(t, err) if assert.Len(t, tokens, 1) { assert.Equal(t, int64(2), tokens[0].UID) assert.Equal(t, "Token A", tokens[0].Name) } - tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100}) + tokens, err = db.Find[auth_model.AccessToken](t.Context(), auth_model.ListAccessTokensOptions{UserID: 100}) assert.NoError(t, err) assert.Empty(t, tokens) } func TestUpdateAccessToken(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "4c6f36e6cf498e2a448662f915d932c09c5a146c") + token, err := auth_model.GetAccessTokenBySHA(t.Context(), "4c6f36e6cf498e2a448662f915d932c09c5a146c") assert.NoError(t, err) token.Name = "Token Z" - assert.NoError(t, auth_model.UpdateAccessToken(db.DefaultContext, token)) + assert.NoError(t, auth_model.UpdateAccessToken(t.Context(), token)) unittest.AssertExistsAndLoadBean(t, token) } func TestDeleteAccessTokenByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "4c6f36e6cf498e2a448662f915d932c09c5a146c") + token, err := auth_model.GetAccessTokenBySHA(t.Context(), "4c6f36e6cf498e2a448662f915d932c09c5a146c") assert.NoError(t, err) assert.Equal(t, int64(1), token.UID) - assert.NoError(t, auth_model.DeleteAccessTokenByID(db.DefaultContext, token.ID, 1)) + assert.NoError(t, auth_model.DeleteAccessTokenByID(t.Context(), token.ID, 1)) unittest.AssertNotExistsBean(t, token) - err = auth_model.DeleteAccessTokenByID(db.DefaultContext, 100, 100) + err = auth_model.DeleteAccessTokenByID(t.Context(), 100, 100) assert.Error(t, err) assert.True(t, auth_model.IsErrAccessTokenNotExist(err)) } diff --git a/models/auth/oauth2_test.go b/models/auth/oauth2_test.go index c6626b283e4..97f750755a2 100644 --- a/models/auth/oauth2_test.go +++ b/models/auth/oauth2_test.go @@ -7,7 +7,6 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" @@ -16,7 +15,7 @@ import ( func TestOAuth2Application_GenerateClientSecret(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) - secret, err := app.GenerateClientSecret(db.DefaultContext) + secret, err := app.GenerateClientSecret(t.Context()) assert.NoError(t, err) assert.NotEmpty(t, secret) unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret}) @@ -26,7 +25,7 @@ func BenchmarkOAuth2Application_GenerateClientSecret(b *testing.B) { assert.NoError(b, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(b, &auth_model.OAuth2Application{ID: 1}) for b.Loop() { - _, _ = app.GenerateClientSecret(db.DefaultContext) + _, _ = app.GenerateClientSecret(b.Context()) } } @@ -76,7 +75,7 @@ func TestOAuth2Application_ContainsRedirect_Slash(t *testing.T) { func TestOAuth2Application_ValidateClientSecret(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) - secret, err := app.GenerateClientSecret(db.DefaultContext) + secret, err := app.GenerateClientSecret(t.Context()) assert.NoError(t, err) assert.True(t, app.ValidateClientSecret([]byte(secret))) assert.False(t, app.ValidateClientSecret([]byte("fewijfowejgfiowjeoifew"))) @@ -84,18 +83,18 @@ func TestOAuth2Application_ValidateClientSecret(t *testing.T) { func TestGetOAuth2ApplicationByClientID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - app, err := auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "da7da3ba-9a13-4167-856f-3899de0b0138") + app, err := auth_model.GetOAuth2ApplicationByClientID(t.Context(), "da7da3ba-9a13-4167-856f-3899de0b0138") assert.NoError(t, err) assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID) - app, err = auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "invalid client id") + app, err = auth_model.GetOAuth2ApplicationByClientID(t.Context(), "invalid client id") assert.Error(t, err) assert.Nil(t, app) } func TestCreateOAuth2Application(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - app, err := auth_model.CreateOAuth2Application(db.DefaultContext, auth_model.CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1}) + app, err := auth_model.CreateOAuth2Application(t.Context(), auth_model.CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1}) assert.NoError(t, err) assert.Equal(t, "newapp", app.Name) assert.Len(t, app.ClientID, 36) @@ -109,11 +108,11 @@ func TestOAuth2Application_TableName(t *testing.T) { func TestOAuth2Application_GetGrantByUserID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) - grant, err := app.GetGrantByUserID(db.DefaultContext, 1) + grant, err := app.GetGrantByUserID(t.Context(), 1) assert.NoError(t, err) assert.Equal(t, int64(1), grant.UserID) - grant, err = app.GetGrantByUserID(db.DefaultContext, 34923458) + grant, err = app.GetGrantByUserID(t.Context(), 34923458) assert.NoError(t, err) assert.Nil(t, grant) } @@ -121,7 +120,7 @@ func TestOAuth2Application_GetGrantByUserID(t *testing.T) { func TestOAuth2Application_CreateGrant(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1}) - grant, err := app.CreateGrant(db.DefaultContext, 2, "") + grant, err := app.CreateGrant(t.Context(), 2, "") assert.NoError(t, err) assert.NotNil(t, grant) assert.Equal(t, int64(2), grant.UserID) @@ -133,11 +132,11 @@ func TestOAuth2Application_CreateGrant(t *testing.T) { func TestGetOAuth2GrantByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - grant, err := auth_model.GetOAuth2GrantByID(db.DefaultContext, 1) + grant, err := auth_model.GetOAuth2GrantByID(t.Context(), 1) assert.NoError(t, err) assert.Equal(t, int64(1), grant.ID) - grant, err = auth_model.GetOAuth2GrantByID(db.DefaultContext, 34923458) + grant, err = auth_model.GetOAuth2GrantByID(t.Context(), 34923458) assert.NoError(t, err) assert.Nil(t, grant) } @@ -145,7 +144,7 @@ func TestGetOAuth2GrantByID(t *testing.T) { func TestOAuth2Grant_IncreaseCounter(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1}) - assert.NoError(t, grant.IncreaseCounter(db.DefaultContext)) + assert.NoError(t, grant.IncreaseCounter(t.Context())) assert.Equal(t, int64(2), grant.Counter) unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2}) } @@ -162,7 +161,7 @@ func TestOAuth2Grant_ScopeContains(t *testing.T) { func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1}) - code, err := grant.GenerateNewAuthorizationCode(db.DefaultContext, "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256") + code, err := grant.GenerateNewAuthorizationCode(t.Context(), "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256") assert.NoError(t, err) assert.NotNil(t, code) assert.Greater(t, len(code.Code), 32) // secret length > 32 @@ -174,20 +173,20 @@ func TestOAuth2Grant_TableName(t *testing.T) { func TestGetOAuth2GrantsByUserID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - result, err := auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 1) + result, err := auth_model.GetOAuth2GrantsByUserID(t.Context(), 1) assert.NoError(t, err) assert.Len(t, result, 1) assert.Equal(t, int64(1), result[0].ID) assert.Equal(t, result[0].ApplicationID, result[0].Application.ID) - result, err = auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 34134) + result, err = auth_model.GetOAuth2GrantsByUserID(t.Context(), 34134) assert.NoError(t, err) assert.Empty(t, result) } func TestRevokeOAuth2Grant(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.NoError(t, auth_model.RevokeOAuth2Grant(db.DefaultContext, 1, 1)) + assert.NoError(t, auth_model.RevokeOAuth2Grant(t.Context(), 1, 1)) unittest.AssertNotExistsBean(t, &auth_model.OAuth2Grant{ID: 1, UserID: 1}) } @@ -195,13 +194,13 @@ func TestRevokeOAuth2Grant(t *testing.T) { func TestGetOAuth2AuthorizationByCode(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - code, err := auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "authcode") + code, err := auth_model.GetOAuth2AuthorizationByCode(t.Context(), "authcode") assert.NoError(t, err) assert.NotNil(t, code) assert.Equal(t, "authcode", code.Code) assert.Equal(t, int64(1), code.ID) - code, err = auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "does not exist") + code, err = auth_model.GetOAuth2AuthorizationByCode(t.Context(), "does not exist") assert.NoError(t, err) assert.Nil(t, code) } @@ -256,7 +255,7 @@ func TestOAuth2AuthorizationCode_GenerateRedirectURI(t *testing.T) { func TestOAuth2AuthorizationCode_Invalidate(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) code := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"}) - assert.NoError(t, code.Invalidate(db.DefaultContext)) + assert.NoError(t, code.Invalidate(t.Context())) unittest.AssertNotExistsBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"}) } diff --git a/models/auth/source_test.go b/models/auth/source_test.go index 64c7460b643..285f55a24b0 100644 --- a/models/auth/source_test.go +++ b/models/auth/source_test.go @@ -14,7 +14,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "xorm.io/xorm" "xorm.io/xorm/schemas" ) @@ -46,7 +45,7 @@ func TestDumpAuthSource(t *testing.T) { auth_model.RegisterTypeConfig(auth_model.OAuth2, new(TestSource)) - auth_model.CreateSource(db.DefaultContext, &auth_model.Source{ + auth_model.CreateSource(t.Context(), &auth_model.Source{ Type: auth_model.OAuth2, Name: "TestSource", IsActive: false, @@ -59,7 +58,7 @@ func TestDumpAuthSource(t *testing.T) { sb := new(strings.Builder) // TODO: this test is quite hacky, it should use a low-level "select" (without model processors) but not a database dump - engine := db.GetEngine(db.DefaultContext).(*xorm.Engine) + engine := unittest.GetXORMEngine() require.NoError(t, engine.DumpTables([]*schemas.Table{authSourceSchema}, sb)) assert.Contains(t, sb.String(), `"Provider":"ConvertibleSourceName"`) } diff --git a/models/auth/webauthn_test.go b/models/auth/webauthn_test.go index 654427e9743..41c5f6de94a 100644 --- a/models/auth/webauthn_test.go +++ b/models/auth/webauthn_test.go @@ -7,7 +7,6 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "github.com/go-webauthn/webauthn/webauthn" @@ -17,11 +16,11 @@ import ( func TestGetWebAuthnCredentialByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - res, err := auth_model.GetWebAuthnCredentialByID(db.DefaultContext, 1) + res, err := auth_model.GetWebAuthnCredentialByID(t.Context(), 1) assert.NoError(t, err) assert.Equal(t, "WebAuthn credential", res.Name) - _, err = auth_model.GetWebAuthnCredentialByID(db.DefaultContext, 342432) + _, err = auth_model.GetWebAuthnCredentialByID(t.Context(), 342432) assert.Error(t, err) assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err)) } @@ -29,7 +28,7 @@ func TestGetWebAuthnCredentialByID(t *testing.T) { func TestGetWebAuthnCredentialsByUID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - res, err := auth_model.GetWebAuthnCredentialsByUID(db.DefaultContext, 32) + res, err := auth_model.GetWebAuthnCredentialsByUID(t.Context(), 32) assert.NoError(t, err) assert.Len(t, res, 1) assert.Equal(t, "WebAuthn credential", res[0].Name) @@ -43,7 +42,7 @@ func TestWebAuthnCredential_UpdateSignCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1}) cred.SignCount = 1 - assert.NoError(t, cred.UpdateSignCount(db.DefaultContext)) + assert.NoError(t, cred.UpdateSignCount(t.Context())) unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1, SignCount: 1}) } @@ -51,14 +50,14 @@ func TestWebAuthnCredential_UpdateLargeCounter(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1}) cred.SignCount = 0xffffffff - assert.NoError(t, cred.UpdateSignCount(db.DefaultContext)) + assert.NoError(t, cred.UpdateSignCount(t.Context())) unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1, SignCount: 0xffffffff}) } func TestCreateCredential(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - res, err := auth_model.CreateCredential(db.DefaultContext, 1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")}) + res, err := auth_model.CreateCredential(t.Context(), 1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")}) assert.NoError(t, err) assert.Equal(t, "WebAuthn Created Credential", res.Name) assert.Equal(t, []byte("Test"), res.CredentialID) diff --git a/models/avatars/avatar_test.go b/models/avatars/avatar_test.go index c8f7a6574bf..43a062cc2a1 100644 --- a/models/avatars/avatar_test.go +++ b/models/avatars/avatar_test.go @@ -7,7 +7,6 @@ import ( "testing" avatars_model "code.gitea.io/gitea/models/avatars" - "code.gitea.io/gitea/models/db" system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting/config" @@ -18,14 +17,14 @@ import ( const gravatarSource = "https://secure.gravatar.com/avatar/" func disableGravatar(t *testing.T) { - err := system_model.SetSettings(db.DefaultContext, map[string]string{setting.Config().Picture.EnableFederatedAvatar.DynKey(): "false"}) + err := system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.EnableFederatedAvatar.DynKey(): "false"}) assert.NoError(t, err) - err = system_model.SetSettings(db.DefaultContext, map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "true"}) + err = system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "true"}) assert.NoError(t, err) } func enableGravatar(t *testing.T) { - err := system_model.SetSettings(db.DefaultContext, map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "false"}) + err := system_model.SetSettings(t.Context(), map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "false"}) assert.NoError(t, err) setting.GravatarSource = gravatarSource } @@ -47,12 +46,12 @@ func TestSizedAvatarLink(t *testing.T) { disableGravatar(t) config.GetDynGetter().InvalidateCache() assert.Equal(t, "/testsuburl/assets/img/avatar_default.png", - avatars_model.GenerateEmailAvatarFastLink(db.DefaultContext, "gitea@example.com", 100)) + avatars_model.GenerateEmailAvatarFastLink(t.Context(), "gitea@example.com", 100)) enableGravatar(t) config.GetDynGetter().InvalidateCache() assert.Equal(t, "https://secure.gravatar.com/avatar/353cbad9b58e69c96154ad99f92bedc7?d=identicon&s=100", - avatars_model.GenerateEmailAvatarFastLink(db.DefaultContext, "gitea@example.com", 100), + avatars_model.GenerateEmailAvatarFastLink(t.Context(), "gitea@example.com", 100), ) } diff --git a/models/db/context.go b/models/db/context.go index ad99ada8c8c..cac97217471 100644 --- a/models/db/context.go +++ b/models/db/context.go @@ -17,26 +17,23 @@ import ( "xorm.io/xorm" ) -// DefaultContext is the default context to run xorm queries in -// will be overwritten by Init with HammerContext -var DefaultContext context.Context - type engineContextKeyType struct{} var engineContextKey = engineContextKeyType{} -// Context represents a db context -type Context struct { +type xormContextType struct { context.Context engine Engine } -func newContext(ctx context.Context, e Engine) *Context { - return &Context{Context: ctx, engine: e} +var xormContext *xormContextType + +func newContext(ctx context.Context, e Engine) *xormContextType { + return &xormContextType{Context: ctx, engine: e} } // Value shadows Value for context.Context but allows us to get ourselves and an Engined object -func (ctx *Context) Value(key any) any { +func (ctx *xormContextType) Value(key any) any { if key == engineContextKey { return ctx } @@ -44,7 +41,7 @@ func (ctx *Context) Value(key any) any { } // WithContext returns this engine tied to this context -func (ctx *Context) WithContext(other context.Context) *Context { +func (ctx *xormContextType) WithContext(other context.Context) *xormContextType { return newContext(ctx, ctx.engine.Context(other)) } @@ -90,20 +87,24 @@ func contextSafetyCheck(e Engine) { } // GetEngine gets an existing db Engine/Statement or creates a new Session -func GetEngine(ctx context.Context) Engine { +func GetEngine(ctx context.Context) (e Engine) { + defer func() { contextSafetyCheck(e) }() if e := getExistingEngine(ctx); e != nil { return e } return xormEngine.Context(ctx) } +func GetXORMEngineForTesting() *xorm.Engine { + return xormEngine +} + // getExistingEngine gets an existing db Engine/Statement from this context or returns nil func getExistingEngine(ctx context.Context) (e Engine) { - defer func() { contextSafetyCheck(e) }() - if engined, ok := ctx.(*Context); ok { + if engined, ok := ctx.(*xormContextType); ok { return engined.engine } - if engined, ok := ctx.Value(engineContextKey).(*Context); ok { + if engined, ok := ctx.Value(engineContextKey).(*xormContextType); ok { return engined.engine } return nil @@ -150,7 +151,7 @@ func (c *halfCommitter) Close() error { // So calling `Commit()` will do nothing, but calling `Close()` without calling `Commit()` will rollback the transaction. // And all operations submitted by the caller stack will be rollbacked as well, not only the operations in the current function. // d. It doesn't mean rollback is forbidden, but always do it only when there is an error, and you do want to rollback. -func TxContext(parentCtx context.Context) (*Context, Committer, error) { +func TxContext(parentCtx context.Context) (context.Context, Committer, error) { if sess, ok := inTransaction(parentCtx); ok { return newContext(parentCtx, sess), &halfCommitter{committer: sess}, nil } @@ -161,7 +162,7 @@ func TxContext(parentCtx context.Context) (*Context, Committer, error) { return nil, nil, err } - return newContext(DefaultContext, sess), sess, nil + return newContext(xormContext, sess), sess, nil } // WithTx represents executing database operations on a transaction, if the transaction exist, diff --git a/models/db/context_committer_test.go b/models/db/context_committer_test.go index 849c5dea411..90f6aaefa1e 100644 --- a/models/db/context_committer_test.go +++ b/models/db/context_committer_test.go @@ -39,7 +39,7 @@ func Test_halfCommitter(t *testing.T) { /* Do something like: - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) if err != nil { return nil } diff --git a/models/db/context_test.go b/models/db/context_test.go index a6bd11d2ae1..1bc84ffbf93 100644 --- a/models/db/context_test.go +++ b/models/db/context_test.go @@ -15,13 +15,13 @@ import ( func TestInTransaction(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.False(t, db.InTransaction(db.DefaultContext)) - assert.NoError(t, db.WithTx(db.DefaultContext, func(ctx context.Context) error { + assert.False(t, db.InTransaction(t.Context())) + assert.NoError(t, db.WithTx(t.Context(), func(ctx context.Context) error { assert.True(t, db.InTransaction(ctx)) return nil })) - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) assert.NoError(t, err) defer committer.Close() assert.True(t, db.InTransaction(ctx)) @@ -35,14 +35,14 @@ func TestTxContext(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) { // create new transaction - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) assert.NoError(t, err) assert.True(t, db.InTransaction(ctx)) assert.NoError(t, committer.Commit()) } { // reuse the transaction created by TxContext and commit it - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) engine := db.GetEngine(ctx) assert.NoError(t, err) assert.True(t, db.InTransaction(ctx)) @@ -57,7 +57,7 @@ func TestTxContext(t *testing.T) { } { // reuse the transaction created by TxContext and close it - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) engine := db.GetEngine(ctx) assert.NoError(t, err) assert.True(t, db.InTransaction(ctx)) @@ -72,7 +72,7 @@ func TestTxContext(t *testing.T) { } { // reuse the transaction created by WithTx - assert.NoError(t, db.WithTx(db.DefaultContext, func(ctx context.Context) error { + assert.NoError(t, db.WithTx(t.Context(), func(ctx context.Context) error { assert.True(t, db.InTransaction(ctx)) { ctx, committer, err := db.TxContext(ctx) @@ -93,16 +93,16 @@ func TestContextSafety(t *testing.T) { ID int64 } assert.NoError(t, unittest.GetXORMEngine().Sync(&TestModel1{}, &TestModel2{})) - assert.NoError(t, db.TruncateBeans(db.DefaultContext, &TestModel1{}, &TestModel2{})) + assert.NoError(t, db.TruncateBeans(t.Context(), &TestModel1{}, &TestModel2{})) testCount := 10 for i := 1; i <= testCount; i++ { - assert.NoError(t, db.Insert(db.DefaultContext, &TestModel1{ID: int64(i)})) - assert.NoError(t, db.Insert(db.DefaultContext, &TestModel2{ID: int64(-i)})) + assert.NoError(t, db.Insert(t.Context(), &TestModel1{ID: int64(i)})) + assert.NoError(t, db.Insert(t.Context(), &TestModel2{ID: int64(-i)})) } actualCount := 0 - // here: db.GetEngine(db.DefaultContext) is a new *Session created from *Engine - _ = db.WithTx(db.DefaultContext, func(ctx context.Context) error { + // here: db.GetEngine(t.Context()) is a new *Session created from *Engine + _ = db.WithTx(t.Context(), func(ctx context.Context) error { _ = db.GetEngine(ctx).Iterate(&TestModel1{}, func(i int, bean any) error { // here: db.GetEngine(ctx) is always the unclosed "Iterate" *Session with autoResetStatement=false, // and the internal states (including "cond" and others) are always there and not be reset in this callback. @@ -123,7 +123,7 @@ func TestContextSafety(t *testing.T) { // deny the bad usages assert.PanicsWithError(t, "using database context in an iterator would cause corrupted results", func() { _ = unittest.GetXORMEngine().Iterate(&TestModel1{}, func(i int, bean any) error { - _ = db.GetEngine(db.DefaultContext) + _ = db.GetEngine(t.Context()) return nil }) }) diff --git a/models/db/engine.go b/models/db/engine.go index ba287d58f07..4b12925b1cd 100755 --- a/models/db/engine.go +++ b/models/db/engine.go @@ -59,8 +59,14 @@ type Engine interface { Cols(...string) *xorm.Session Context(ctx context.Context) *xorm.Session Ping() error + IsTableExist(tableNameOrBean any) (bool, error) } +var ( + _ Engine = (*xorm.Engine)(nil) + _ Engine = (*xorm.Session)(nil) +) + // TableInfo returns table's information via an object func TableInfo(v any) (*schemas.Table, error) { return xormEngine.TableInfo(v) diff --git a/models/db/engine_init.go b/models/db/engine_init.go index bb02aff274a..373a99e7b52 100644 --- a/models/db/engine_init.go +++ b/models/db/engine_init.go @@ -52,7 +52,7 @@ func newXORMEngine() (*xorm.Engine, error) { return engine, nil } -// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext +// InitEngine initializes the xorm.Engine and sets it as XORM's default context func InitEngine(ctx context.Context) error { xe, err := newXORMEngine() if err != nil { @@ -70,7 +70,6 @@ func InitEngine(ctx context.Context) error { xe.SetMaxOpenConns(setting.Database.MaxOpenConns) xe.SetMaxIdleConns(setting.Database.MaxIdleConns) xe.SetConnMaxLifetime(setting.Database.ConnMaxLifetime) - xe.SetDefaultContext(ctx) if setting.Database.SlowQueryThreshold > 0 { xe.AddHook(&EngineHook{ @@ -86,22 +85,23 @@ func InitEngine(ctx context.Context) error { // SetDefaultEngine sets the default engine for db func SetDefaultEngine(ctx context.Context, eng *xorm.Engine) { xormEngine = eng - DefaultContext = &Context{Context: ctx, engine: xormEngine} + xormEngine.SetDefaultContext(ctx) + xormContext = &xormContextType{Context: ctx, engine: xormEngine} } // UnsetDefaultEngine closes and unsets the default engine // We hope the SetDefaultEngine and UnsetDefaultEngine can be paired, but it's impossible now, -// there are many calls to InitEngine -> SetDefaultEngine directly to overwrite the `xormEngine` and DefaultContext without close +// there are many calls to InitEngine -> SetDefaultEngine directly to overwrite the `xormEngine` and `xormContext` without close // Global database engine related functions are all racy and there is no graceful close right now. func UnsetDefaultEngine() { if xormEngine != nil { _ = xormEngine.Close() xormEngine = nil } - DefaultContext = nil + xormContext = nil } -// InitEngineWithMigration initializes a new xorm.Engine and sets it as the db.DefaultContext +// InitEngineWithMigration initializes a new xorm.Engine and sets it as the XORM's default context // This function must never call .Sync() if the provided migration function fails. // When called from the "doctor" command, the migration function is a version check // that prevents the doctor from fixing anything in the database if the migration level diff --git a/models/db/engine_test.go b/models/db/engine_test.go index a236f83735e..167525a5a8a 100644 --- a/models/db/engine_test.go +++ b/models/db/engine_test.go @@ -27,7 +27,7 @@ func TestDumpDatabase(t *testing.T) { ID int64 `xorm:"pk autoincr"` Version int64 } - assert.NoError(t, db.GetEngine(db.DefaultContext).Sync(new(Version))) + assert.NoError(t, db.GetEngine(t.Context()).Sync(new(Version))) for _, dbType := range setting.SupportedDatabaseTypes { assert.NoError(t, db.DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType)) @@ -37,20 +37,20 @@ func TestDumpDatabase(t *testing.T) { func TestDeleteOrphanedObjects(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - countBefore, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) + countBefore, err := db.GetEngine(t.Context()).Count(&issues_model.PullRequest{}) assert.NoError(t, err) - _, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) + _, err = db.GetEngine(t.Context()).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) assert.NoError(t, err) - orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") + orphaned, err := db.CountOrphanedObjects(t.Context(), "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) assert.EqualValues(t, 3, orphaned) - err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") + err = db.DeleteOrphanedObjects(t.Context(), "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) - countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) + countAfter, err := db.GetEngine(t.Context()).Count(&issues_model.PullRequest{}) assert.NoError(t, err) assert.Equal(t, countBefore, countAfter) } diff --git a/models/db/index_test.go b/models/db/index_test.go index 5fce0a60129..e2af7f35bb1 100644 --- a/models/db/index_test.go +++ b/models/db/index_test.go @@ -35,30 +35,30 @@ func TestSyncMaxResourceIndex(t *testing.T) { xe := unittest.GetXORMEngine() assert.NoError(t, xe.Sync(&TestIndex{})) - err := db.SyncMaxResourceIndex(db.DefaultContext, "test_index", 10, 51) + err := db.SyncMaxResourceIndex(t.Context(), "test_index", 10, 51) assert.NoError(t, err) // sync new max index - maxIndex, err := getCurrentResourceIndex(db.DefaultContext, "test_index", 10) + maxIndex, err := getCurrentResourceIndex(t.Context(), "test_index", 10) assert.NoError(t, err) assert.EqualValues(t, 51, maxIndex) // smaller index doesn't change - err = db.SyncMaxResourceIndex(db.DefaultContext, "test_index", 10, 30) + err = db.SyncMaxResourceIndex(t.Context(), "test_index", 10, 30) assert.NoError(t, err) - maxIndex, err = getCurrentResourceIndex(db.DefaultContext, "test_index", 10) + maxIndex, err = getCurrentResourceIndex(t.Context(), "test_index", 10) assert.NoError(t, err) assert.EqualValues(t, 51, maxIndex) // larger index changes - err = db.SyncMaxResourceIndex(db.DefaultContext, "test_index", 10, 62) + err = db.SyncMaxResourceIndex(t.Context(), "test_index", 10, 62) assert.NoError(t, err) - maxIndex, err = getCurrentResourceIndex(db.DefaultContext, "test_index", 10) + maxIndex, err = getCurrentResourceIndex(t.Context(), "test_index", 10) assert.NoError(t, err) assert.EqualValues(t, 62, maxIndex) // commit transaction - err = db.WithTx(db.DefaultContext, func(ctx context.Context) error { + err = db.WithTx(t.Context(), func(ctx context.Context) error { err = db.SyncMaxResourceIndex(ctx, "test_index", 10, 73) assert.NoError(t, err) maxIndex, err = getCurrentResourceIndex(ctx, "test_index", 10) @@ -67,12 +67,12 @@ func TestSyncMaxResourceIndex(t *testing.T) { return nil }) assert.NoError(t, err) - maxIndex, err = getCurrentResourceIndex(db.DefaultContext, "test_index", 10) + maxIndex, err = getCurrentResourceIndex(t.Context(), "test_index", 10) assert.NoError(t, err) assert.EqualValues(t, 73, maxIndex) // rollback transaction - err = db.WithTx(db.DefaultContext, func(ctx context.Context) error { + err = db.WithTx(t.Context(), func(ctx context.Context) error { err = db.SyncMaxResourceIndex(ctx, "test_index", 10, 84) maxIndex, err = getCurrentResourceIndex(ctx, "test_index", 10) assert.NoError(t, err) @@ -80,7 +80,7 @@ func TestSyncMaxResourceIndex(t *testing.T) { return errors.New("test rollback") }) assert.Error(t, err) - maxIndex, err = getCurrentResourceIndex(db.DefaultContext, "test_index", 10) + maxIndex, err = getCurrentResourceIndex(t.Context(), "test_index", 10) assert.NoError(t, err) assert.EqualValues(t, 73, maxIndex) // the max index doesn't change because the transaction was rolled back } @@ -91,36 +91,36 @@ func TestGetNextResourceIndex(t *testing.T) { assert.NoError(t, xe.Sync(&TestIndex{})) // create a new record - maxIndex, err := db.GetNextResourceIndex(db.DefaultContext, "test_index", 20) + maxIndex, err := db.GetNextResourceIndex(t.Context(), "test_index", 20) assert.NoError(t, err) assert.EqualValues(t, 1, maxIndex) // increase the existing record - maxIndex, err = db.GetNextResourceIndex(db.DefaultContext, "test_index", 20) + maxIndex, err = db.GetNextResourceIndex(t.Context(), "test_index", 20) assert.NoError(t, err) assert.EqualValues(t, 2, maxIndex) // commit transaction - err = db.WithTx(db.DefaultContext, func(ctx context.Context) error { + err = db.WithTx(t.Context(), func(ctx context.Context) error { maxIndex, err = db.GetNextResourceIndex(ctx, "test_index", 20) assert.NoError(t, err) assert.EqualValues(t, 3, maxIndex) return nil }) assert.NoError(t, err) - maxIndex, err = getCurrentResourceIndex(db.DefaultContext, "test_index", 20) + maxIndex, err = getCurrentResourceIndex(t.Context(), "test_index", 20) assert.NoError(t, err) assert.EqualValues(t, 3, maxIndex) // rollback transaction - err = db.WithTx(db.DefaultContext, func(ctx context.Context) error { + err = db.WithTx(t.Context(), func(ctx context.Context) error { maxIndex, err = db.GetNextResourceIndex(ctx, "test_index", 20) assert.NoError(t, err) assert.EqualValues(t, 4, maxIndex) return errors.New("test rollback") }) assert.Error(t, err) - maxIndex, err = getCurrentResourceIndex(db.DefaultContext, "test_index", 20) + maxIndex, err = getCurrentResourceIndex(t.Context(), "test_index", 20) assert.NoError(t, err) assert.EqualValues(t, 3, maxIndex) // the max index doesn't change because the transaction was rolled back } diff --git a/models/db/install/db.go b/models/db/install/db.go index 1b3b2ec3e99..a84e5e54fe6 100644 --- a/models/db/install/db.go +++ b/models/db/install/db.go @@ -4,27 +4,22 @@ package install import ( + "context" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/setting" - - "xorm.io/xorm" ) -func getXORMEngine() *xorm.Engine { - return db.GetEngine(db.DefaultContext).(*xorm.Engine) -} - // CheckDatabaseConnection checks the database connection -func CheckDatabaseConnection() error { - e := db.GetEngine(db.DefaultContext) - _, err := e.Exec("SELECT 1") +func CheckDatabaseConnection(ctx context.Context) error { + _, err := db.GetEngine(ctx).Exec("SELECT 1") return err } // GetMigrationVersion gets the database migration version -func GetMigrationVersion() (int64, error) { +func GetMigrationVersion(ctx context.Context) (int64, error) { var installedDbVersion int64 - x := getXORMEngine() + x := db.GetEngine(ctx) exist, err := x.IsTableExist("version") if err != nil { return 0, err @@ -40,8 +35,8 @@ func GetMigrationVersion() (int64, error) { } // HasPostInstallationUsers checks whether there are users after installation -func HasPostInstallationUsers() (bool, error) { - x := getXORMEngine() +func HasPostInstallationUsers(ctx context.Context) (bool, error) { + x := db.GetEngine(ctx) exist, err := x.IsTableExist("user") if err != nil { return false, err diff --git a/models/db/iterate_test.go b/models/db/iterate_test.go index e9f27906711..21bb0c0b4bb 100644 --- a/models/db/iterate_test.go +++ b/models/db/iterate_test.go @@ -19,18 +19,18 @@ func TestIterate(t *testing.T) { xe := unittest.GetXORMEngine() assert.NoError(t, xe.Sync(&repo_model.RepoUnit{})) - cnt, err := db.GetEngine(db.DefaultContext).Count(&repo_model.RepoUnit{}) + cnt, err := db.GetEngine(t.Context()).Count(&repo_model.RepoUnit{}) assert.NoError(t, err) var repoUnitCnt int - err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repo *repo_model.RepoUnit) error { + err = db.Iterate(t.Context(), nil, func(ctx context.Context, repo *repo_model.RepoUnit) error { repoUnitCnt++ return nil }) assert.NoError(t, err) assert.EqualValues(t, cnt, repoUnitCnt) - err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error { + err = db.Iterate(t.Context(), nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error { has, err := db.ExistByID[repo_model.RepoUnit](ctx, repoUnit.ID) if err != nil { return err diff --git a/models/db/list_test.go b/models/db/list_test.go index 170473a9689..ddcfff1f88d 100644 --- a/models/db/list_test.go +++ b/models/db/list_test.go @@ -32,20 +32,20 @@ func TestFind(t *testing.T) { assert.NoError(t, xe.Sync(&repo_model.RepoUnit{})) var repoUnitCount int - _, err := db.GetEngine(db.DefaultContext).SQL("SELECT COUNT(*) FROM repo_unit").Get(&repoUnitCount) + _, err := db.GetEngine(t.Context()).SQL("SELECT COUNT(*) FROM repo_unit").Get(&repoUnitCount) assert.NoError(t, err) assert.NotEmpty(t, repoUnitCount) opts := mockListOptions{} - repoUnits, err := db.Find[repo_model.RepoUnit](db.DefaultContext, opts) + repoUnits, err := db.Find[repo_model.RepoUnit](t.Context(), opts) assert.NoError(t, err) assert.Len(t, repoUnits, repoUnitCount) - cnt, err := db.Count[repo_model.RepoUnit](db.DefaultContext, opts) + cnt, err := db.Count[repo_model.RepoUnit](t.Context(), opts) assert.NoError(t, err) assert.EqualValues(t, repoUnitCount, cnt) - repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](db.DefaultContext, opts) + repoUnits, newCnt, err := db.FindAndCount[repo_model.RepoUnit](t.Context(), opts) assert.NoError(t, err) assert.Equal(t, cnt, newCnt) assert.Len(t, repoUnits, repoUnitCount) diff --git a/models/dbfs/dbfs_test.go b/models/dbfs/dbfs_test.go index 0257d2bd15d..e1ecd871e4d 100644 --- a/models/dbfs/dbfs_test.go +++ b/models/dbfs/dbfs_test.go @@ -9,8 +9,6 @@ import ( "os" "testing" - "code.gitea.io/gitea/models/db" - "github.com/stretchr/testify/assert" ) @@ -26,7 +24,7 @@ func TestDbfsBasic(t *testing.T) { defer changeDefaultFileBlockSize(4)() // test basic write/read - f, err := OpenFile(db.DefaultContext, "test.txt", os.O_RDWR|os.O_CREATE) + f, err := OpenFile(t.Context(), "test.txt", os.O_RDWR|os.O_CREATE) assert.NoError(t, err) n, err := f.Write([]byte("0123456789")) // blocks: 0123 4567 89 @@ -95,25 +93,25 @@ func TestDbfsBasic(t *testing.T) { assert.NoError(t, f.Close()) // test rename - err = Rename(db.DefaultContext, "test.txt", "test2.txt") + err = Rename(t.Context(), "test.txt", "test2.txt") assert.NoError(t, err) - _, err = OpenFile(db.DefaultContext, "test.txt", os.O_RDONLY) + _, err = OpenFile(t.Context(), "test.txt", os.O_RDONLY) assert.Error(t, err) - f, err = OpenFile(db.DefaultContext, "test2.txt", os.O_RDONLY) + f, err = OpenFile(t.Context(), "test2.txt", os.O_RDONLY) assert.NoError(t, err) assert.NoError(t, f.Close()) // test remove - err = Remove(db.DefaultContext, "test2.txt") + err = Remove(t.Context(), "test2.txt") assert.NoError(t, err) - _, err = OpenFile(db.DefaultContext, "test2.txt", os.O_RDONLY) + _, err = OpenFile(t.Context(), "test2.txt", os.O_RDONLY) assert.Error(t, err) // test stat - f, err = OpenFile(db.DefaultContext, "test/test.txt", os.O_RDWR|os.O_CREATE) + f, err = OpenFile(t.Context(), "test/test.txt", os.O_RDWR|os.O_CREATE) assert.NoError(t, err) stat, err := f.Stat() assert.NoError(t, err) @@ -129,11 +127,11 @@ func TestDbfsBasic(t *testing.T) { func TestDbfsReadWrite(t *testing.T) { defer changeDefaultFileBlockSize(4)() - f1, err := OpenFile(db.DefaultContext, "test.log", os.O_RDWR|os.O_CREATE) + f1, err := OpenFile(t.Context(), "test.log", os.O_RDWR|os.O_CREATE) assert.NoError(t, err) defer f1.Close() - f2, err := OpenFile(db.DefaultContext, "test.log", os.O_RDONLY) + f2, err := OpenFile(t.Context(), "test.log", os.O_RDONLY) assert.NoError(t, err) defer f2.Close() @@ -161,7 +159,7 @@ func TestDbfsReadWrite(t *testing.T) { func TestDbfsSeekWrite(t *testing.T) { defer changeDefaultFileBlockSize(4)() - f, err := OpenFile(db.DefaultContext, "test2.log", os.O_RDWR|os.O_CREATE) + f, err := OpenFile(t.Context(), "test2.log", os.O_RDWR|os.O_CREATE) assert.NoError(t, err) defer f.Close() @@ -180,7 +178,7 @@ func TestDbfsSeekWrite(t *testing.T) { _, err = f.Write([]byte("333")) assert.NoError(t, err) - fr, err := OpenFile(db.DefaultContext, "test2.log", os.O_RDONLY) + fr, err := OpenFile(t.Context(), "test2.log", os.O_RDONLY) assert.NoError(t, err) defer f.Close() diff --git a/models/git/branch_test.go b/models/git/branch_test.go index 252dcc56900..5be435172b8 100644 --- a/models/git/branch_test.go +++ b/models/git/branch_test.go @@ -25,8 +25,8 @@ func TestAddDeletedBranch(t *testing.T) { firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1}) assert.True(t, firstBranch.IsDeleted) - assert.NoError(t, git_model.AddDeletedBranch(db.DefaultContext, repo.ID, firstBranch.Name, firstBranch.DeletedByID)) - assert.NoError(t, git_model.AddDeletedBranch(db.DefaultContext, repo.ID, "branch2", int64(1))) + assert.NoError(t, git_model.AddDeletedBranch(t.Context(), repo.ID, firstBranch.Name, firstBranch.DeletedByID)) + assert.NoError(t, git_model.AddDeletedBranch(t.Context(), repo.ID, "branch2", int64(1))) secondBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "branch2"}) assert.True(t, secondBranch.IsDeleted) @@ -39,7 +39,7 @@ func TestAddDeletedBranch(t *testing.T) { }, } - _, err := git_model.UpdateBranch(db.DefaultContext, repo.ID, secondBranch.PusherID, secondBranch.Name, commit) + _, err := git_model.UpdateBranch(t.Context(), repo.ID, secondBranch.PusherID, secondBranch.Name, commit) assert.NoError(t, err) } @@ -47,7 +47,7 @@ func TestGetDeletedBranches(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - branches, err := db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{ + branches, err := db.Find[git_model.Branch](t.Context(), git_model.FindBranchOptions{ ListOptions: db.ListOptionsAll, RepoID: repo.ID, IsDeletedBranch: optional.Some(true), @@ -71,13 +71,13 @@ func TestDeletedBranchLoadUser(t *testing.T) { branch := getDeletedBranch(t, firstBranch) assert.Nil(t, branch.DeletedBy) - branch.LoadDeletedBy(db.DefaultContext) + branch.LoadDeletedBy(t.Context()) assert.NotNil(t, branch.DeletedBy) assert.Equal(t, "user1", branch.DeletedBy.Name) branch = getDeletedBranch(t, secondBranch) assert.Nil(t, branch.DeletedBy) - branch.LoadDeletedBy(db.DefaultContext) + branch.LoadDeletedBy(t.Context()) assert.NotNil(t, branch.DeletedBy) assert.Equal(t, "Ghost", branch.DeletedBy.Name) } @@ -88,7 +88,7 @@ func TestRemoveDeletedBranch(t *testing.T) { firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1}) - err := git_model.RemoveDeletedBranchByID(db.DefaultContext, repo.ID, 1) + err := git_model.RemoveDeletedBranchByID(t.Context(), repo.ID, 1) assert.NoError(t, err) unittest.AssertNotExistsBean(t, firstBranch) unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 2}) @@ -97,7 +97,7 @@ func TestRemoveDeletedBranch(t *testing.T) { func getDeletedBranch(t *testing.T, branch *git_model.Branch) *git_model.Branch { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - deletedBranch, err := git_model.GetDeletedBranchByID(db.DefaultContext, repo.ID, branch.ID) + deletedBranch, err := git_model.GetDeletedBranchByID(t.Context(), repo.ID, branch.ID) assert.NoError(t, err) assert.Equal(t, branch.ID, deletedBranch.ID) assert.Equal(t, branch.Name, deletedBranch.Name) @@ -109,12 +109,12 @@ func getDeletedBranch(t *testing.T, branch *git_model.Branch) *git_model.Branch func TestFindRenamedBranch(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - branch, exist, err := git_model.FindRenamedBranch(db.DefaultContext, 1, "dev") + branch, exist, err := git_model.FindRenamedBranch(t.Context(), 1, "dev") assert.NoError(t, err) assert.True(t, exist) assert.Equal(t, "master", branch.To) - _, exist, err = git_model.FindRenamedBranch(db.DefaultContext, 1, "unknow") + _, exist, err = git_model.FindRenamedBranch(t.Context(), 1, "unknow") assert.NoError(t, err) assert.False(t, exist) } @@ -124,7 +124,7 @@ func TestRenameBranch(t *testing.T) { repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) _isDefault := false - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) defer committer.Close() assert.NoError(t, err) assert.NoError(t, git_model.UpdateProtectBranch(ctx, repo1, &git_model.ProtectedBranch{ @@ -133,7 +133,7 @@ func TestRenameBranch(t *testing.T) { }, git_model.WhitelistOptions{})) assert.NoError(t, committer.Commit()) - assert.NoError(t, git_model.RenameBranch(db.DefaultContext, repo1, "master", "main", func(ctx context.Context, isDefault bool) error { + assert.NoError(t, git_model.RenameBranch(t.Context(), repo1, "master", "main", func(ctx context.Context, isDefault bool) error { _isDefault = isDefault return nil })) @@ -167,7 +167,7 @@ func TestOnlyGetDeletedBranchOnCorrectRepo(t *testing.T) { // is actually on repo with ID 1. repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - deletedBranch, err := git_model.GetDeletedBranchByID(db.DefaultContext, repo2.ID, 1) + deletedBranch, err := git_model.GetDeletedBranchByID(t.Context(), repo2.ID, 1) // Expect error, and the returned branch is nil. assert.Error(t, err) @@ -177,7 +177,7 @@ func TestOnlyGetDeletedBranchOnCorrectRepo(t *testing.T) { // This should return the deletedBranch. repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - deletedBranch, err = git_model.GetDeletedBranchByID(db.DefaultContext, repo1.ID, 1) + deletedBranch, err = git_model.GetDeletedBranchByID(t.Context(), repo1.ID, 1) // Expect no error, and the returned branch to be not nil. assert.NoError(t, err) diff --git a/models/git/commit_status_test.go b/models/git/commit_status_test.go index 4c0f5e891b2..d1b9dfc3bf9 100644 --- a/models/git/commit_status_test.go +++ b/models/git/commit_status_test.go @@ -15,7 +15,6 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/commitstatus" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "github.com/stretchr/testify/assert" @@ -28,7 +27,7 @@ func TestGetCommitStatuses(t *testing.T) { sha1 := "1234123412341234123412341234123412341234" // the mocked commit ID in test fixtures - statuses, maxResults, err := db.FindAndCount[git_model.CommitStatus](db.DefaultContext, &git_model.CommitStatusOptions{ + statuses, maxResults, err := db.FindAndCount[git_model.CommitStatus](t.Context(), &git_model.CommitStatusOptions{ ListOptions: db.ListOptions{Page: 1, PageSize: 50}, RepoID: repo1.ID, SHA: sha1, @@ -39,25 +38,25 @@ func TestGetCommitStatuses(t *testing.T) { assert.Equal(t, "ci/awesomeness", statuses[0].Context) assert.Equal(t, commitstatus.CommitStatusPending, statuses[0].State) - assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL(db.DefaultContext)) + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL(t.Context())) assert.Equal(t, "cov/awesomeness", statuses[1].Context) assert.Equal(t, commitstatus.CommitStatusWarning, statuses[1].State) - assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL(db.DefaultContext)) + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL(t.Context())) assert.Equal(t, "cov/awesomeness", statuses[2].Context) assert.Equal(t, commitstatus.CommitStatusSuccess, statuses[2].State) - assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL(db.DefaultContext)) + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL(t.Context())) assert.Equal(t, "ci/awesomeness", statuses[3].Context) assert.Equal(t, commitstatus.CommitStatusFailure, statuses[3].State) - assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[3].APIURL(db.DefaultContext)) + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[3].APIURL(t.Context())) assert.Equal(t, "deploy/awesomeness", statuses[4].Context) assert.Equal(t, commitstatus.CommitStatusError, statuses[4].State) - assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL(db.DefaultContext)) + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL(t.Context())) - statuses, maxResults, err = db.FindAndCount[git_model.CommitStatus](db.DefaultContext, &git_model.CommitStatusOptions{ + statuses, maxResults, err = db.FindAndCount[git_model.CommitStatus](t.Context(), &git_model.CommitStatusOptions{ ListOptions: db.ListOptions{Page: 2, PageSize: 50}, RepoID: repo1.ID, SHA: sha1, @@ -187,7 +186,7 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo2) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo2) assert.NoError(t, err) defer gitRepo.Close() @@ -195,7 +194,7 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { assert.NoError(t, err) defer func() { - _, err := db.DeleteByBean(db.DefaultContext, &git_model.CommitStatus{ + _, err := db.DeleteByBean(t.Context(), &git_model.CommitStatus{ RepoID: repo2.ID, CreatorID: user2.ID, SHA: commit.ID.String(), @@ -203,7 +202,7 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { assert.NoError(t, err) }() - err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{ + err = git_model.NewCommitStatus(t.Context(), git_model.NewCommitStatusOptions{ Repo: repo2, Creator: user2, SHA: commit.ID, @@ -215,7 +214,7 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { }) assert.NoError(t, err) - err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{ + err = git_model.NewCommitStatus(t.Context(), git_model.NewCommitStatusOptions{ Repo: repo2, Creator: user2, SHA: commit.ID, @@ -227,7 +226,7 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { }) assert.NoError(t, err) - contexts, err := git_model.FindRepoRecentCommitStatusContexts(db.DefaultContext, repo2.ID, time.Hour) + contexts, err := git_model.FindRepoRecentCommitStatusContexts(t.Context(), repo2.ID, time.Hour) assert.NoError(t, err) if assert.Len(t, contexts, 1) { assert.Equal(t, "compliance/lint-backend", contexts[0]) @@ -239,7 +238,7 @@ func TestCommitStatusesHideActionsURL(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 791, RepoID: repo.ID}) - assert.NoError(t, run.LoadAttributes(db.DefaultContext)) + assert.NoError(t, run.LoadAttributes(t.Context())) statuses := []*git_model.CommitStatus{ { @@ -252,7 +251,7 @@ func TestCommitStatusesHideActionsURL(t *testing.T) { }, } - git_model.CommitStatusesHideActionsURL(db.DefaultContext, statuses) + git_model.CommitStatusesHideActionsURL(t.Context(), statuses) assert.Empty(t, statuses[0].TargetURL) assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL) } @@ -264,7 +263,7 @@ func TestGetCountLatestCommitStatus(t *testing.T) { sha1 := "1234123412341234123412341234123412341234" // the mocked commit ID in test fixtures - commitStatuses, err := git_model.GetLatestCommitStatus(db.DefaultContext, repo1.ID, sha1, db.ListOptions{ + commitStatuses, err := git_model.GetLatestCommitStatus(t.Context(), repo1.ID, sha1, db.ListOptions{ Page: 1, PageSize: 2, }) @@ -275,7 +274,7 @@ func TestGetCountLatestCommitStatus(t *testing.T) { assert.Equal(t, commitstatus.CommitStatusError, commitStatuses[1].State) assert.Equal(t, "deploy/awesomeness", commitStatuses[1].Context) - count, err := git_model.CountLatestCommitStatus(db.DefaultContext, repo1.ID, sha1) + count, err := git_model.CountLatestCommitStatus(t.Context(), repo1.ID, sha1) assert.NoError(t, err) assert.EqualValues(t, 3, count) } diff --git a/models/git/protected_branch_test.go b/models/git/protected_branch_test.go index 367992081d5..3aa1d7daa8a 100644 --- a/models/git/protected_branch_test.go +++ b/models/git/protected_branch_test.go @@ -105,17 +105,17 @@ func TestUpdateProtectBranchPriorities(t *testing.T) { } for _, pb := range protectedBranches { - _, err := db.GetEngine(db.DefaultContext).Insert(pb) + _, err := db.GetEngine(t.Context()).Insert(pb) assert.NoError(t, err) } // Test updating priorities newPriorities := []int64{protectedBranches[2].ID, protectedBranches[0].ID, protectedBranches[1].ID} - err := UpdateProtectBranchPriorities(db.DefaultContext, repo, newPriorities) + err := UpdateProtectBranchPriorities(t.Context(), repo, newPriorities) assert.NoError(t, err) // Verify new priorities - pbs, err := FindRepoProtectedBranchRules(db.DefaultContext, repo.ID) + pbs, err := FindRepoProtectedBranchRules(t.Context(), repo.ID) assert.NoError(t, err) expectedPriorities := map[string]int64{ @@ -133,7 +133,7 @@ func TestNewProtectBranchPriority(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - err := UpdateProtectBranch(db.DefaultContext, repo, &ProtectedBranch{ + err := UpdateProtectBranch(t.Context(), repo, &ProtectedBranch{ RepoID: repo.ID, RuleName: "branch-1", Priority: 1, @@ -146,10 +146,10 @@ func TestNewProtectBranchPriority(t *testing.T) { // Priority intentionally omitted } - err = UpdateProtectBranch(db.DefaultContext, repo, newPB, WhitelistOptions{}) + err = UpdateProtectBranch(t.Context(), repo, newPB, WhitelistOptions{}) assert.NoError(t, err) - savedPB2, err := GetFirstMatchProtectedBranchRule(db.DefaultContext, repo.ID, "branch-2") + savedPB2, err := GetFirstMatchProtectedBranchRule(t.Context(), repo.ID, "branch-2") assert.NoError(t, err) assert.Equal(t, int64(2), savedPB2.Priority) } diff --git a/models/git/protected_tag_test.go b/models/git/protected_tag_test.go index 164c33e28fd..252eaf1bbae 100644 --- a/models/git/protected_tag_test.go +++ b/models/git/protected_tag_test.go @@ -6,7 +6,6 @@ package git_test import ( "testing" - "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" "code.gitea.io/gitea/models/unittest" @@ -17,29 +16,29 @@ func TestIsUserAllowed(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pt := &git_model.ProtectedTag{} - allowed, err := git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) + allowed, err := git_model.IsUserAllowedModifyTag(t.Context(), pt, 1) assert.NoError(t, err) assert.False(t, allowed) pt = &git_model.ProtectedTag{ AllowlistUserIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(t.Context(), pt, 1) assert.NoError(t, err) assert.True(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(t.Context(), pt, 2) assert.NoError(t, err) assert.False(t, allowed) pt = &git_model.ProtectedTag{ AllowlistTeamIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(t.Context(), pt, 1) assert.NoError(t, err) assert.False(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(t.Context(), pt, 2) assert.NoError(t, err) assert.True(t, allowed) @@ -47,11 +46,11 @@ func TestIsUserAllowed(t *testing.T) { AllowlistUserIDs: []int64{1}, AllowlistTeamIDs: []int64{1}, } - allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) + allowed, err = git_model.IsUserAllowedModifyTag(t.Context(), pt, 1) assert.NoError(t, err) assert.True(t, allowed) - allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) + allowed, err = git_model.IsUserAllowedModifyTag(t.Context(), pt, 2) assert.NoError(t, err) assert.True(t, allowed) } @@ -135,7 +134,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) { } for n, c := range cases { - isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) + isAllowed, err := git_model.IsUserAllowedToControlTag(t.Context(), protectedTags, c.name, c.userid) assert.NoError(t, err) assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n) } @@ -157,7 +156,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) { } for n, c := range cases { - isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) + isAllowed, err := git_model.IsUserAllowedToControlTag(t.Context(), protectedTags, c.name, c.userid) assert.NoError(t, err) assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n) } diff --git a/models/issues/assignees_test.go b/models/issues/assignees_test.go index 2c33efd99e6..13922899dc0 100644 --- a/models/issues/assignees_test.go +++ b/models/issues/assignees_test.go @@ -6,7 +6,6 @@ package issues_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -18,35 +17,35 @@ func TestUpdateAssignee(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // Fake issue with assignees - issue, err := issues_model.GetIssueByID(db.DefaultContext, 1) + issue, err := issues_model.GetIssueByID(t.Context(), 1) assert.NoError(t, err) - err = issue.LoadAttributes(db.DefaultContext) + err = issue.LoadAttributes(t.Context()) assert.NoError(t, err) // Assign multiple users - user2, err := user_model.GetUserByID(db.DefaultContext, 2) + user2, err := user_model.GetUserByID(t.Context(), 2) assert.NoError(t, err) - _, _, err = issues_model.ToggleIssueAssignee(db.DefaultContext, issue, &user_model.User{ID: 1}, user2.ID) + _, _, err = issues_model.ToggleIssueAssignee(t.Context(), issue, &user_model.User{ID: 1}, user2.ID) assert.NoError(t, err) - org3, err := user_model.GetUserByID(db.DefaultContext, 3) + org3, err := user_model.GetUserByID(t.Context(), 3) assert.NoError(t, err) - _, _, err = issues_model.ToggleIssueAssignee(db.DefaultContext, issue, &user_model.User{ID: 1}, org3.ID) + _, _, err = issues_model.ToggleIssueAssignee(t.Context(), issue, &user_model.User{ID: 1}, org3.ID) assert.NoError(t, err) - user1, err := user_model.GetUserByID(db.DefaultContext, 1) // This user is already assigned (see the definition in fixtures), so running UpdateAssignee should unassign him + user1, err := user_model.GetUserByID(t.Context(), 1) // This user is already assigned (see the definition in fixtures), so running UpdateAssignee should unassign him assert.NoError(t, err) - _, _, err = issues_model.ToggleIssueAssignee(db.DefaultContext, issue, &user_model.User{ID: 1}, user1.ID) + _, _, err = issues_model.ToggleIssueAssignee(t.Context(), issue, &user_model.User{ID: 1}, user1.ID) assert.NoError(t, err) // Check if he got removed - isAssigned, err := issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, user1) + isAssigned, err := issues_model.IsUserAssignedToIssue(t.Context(), issue, user1) assert.NoError(t, err) assert.False(t, isAssigned) // Check if they're all there - err = issue.LoadAssignees(db.DefaultContext) + err = issue.LoadAssignees(t.Context()) assert.NoError(t, err) var expectedAssignees []*user_model.User @@ -57,12 +56,12 @@ func TestUpdateAssignee(t *testing.T) { } // Check if the user is assigned - isAssigned, err = issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, user2) + isAssigned, err = issues_model.IsUserAssignedToIssue(t.Context(), issue, user2) assert.NoError(t, err) assert.True(t, isAssigned) // This user should not be assigned - isAssigned, err = issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, &user_model.User{ID: 4}) + isAssigned, err = issues_model.IsUserAssignedToIssue(t.Context(), issue, &user_model.User{ID: 4}) assert.NoError(t, err) assert.False(t, isAssigned) } @@ -73,22 +72,22 @@ func TestMakeIDsFromAPIAssigneesToAdd(t *testing.T) { _ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) _ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{""}) + IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "", []string{""}) assert.NoError(t, err) assert.Equal(t, []int64{}, IDs) - _, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"none_existing_user"}) + _, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "", []string{"none_existing_user"}) assert.Error(t, err) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user1", []string{"user1"}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "user1", []string{"user1"}) assert.NoError(t, err) assert.Equal(t, []int64{1}, IDs) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user2", []string{""}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "user2", []string{""}) assert.NoError(t, err) assert.Equal(t, []int64{2}, IDs) - IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"user1", "user2"}) + IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(t.Context(), "", []string{"user1", "user2"}) assert.NoError(t, err) assert.Equal(t, []int64{1, 2}, IDs) } diff --git a/models/issues/comment.go b/models/issues/comment.go index 141ec0027c8..309ee8bbe78 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -414,7 +414,7 @@ func (c *Comment) HTMLURL(ctx context.Context) string { log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" } - return c.Issue.HTMLURL() + c.hashLink(ctx) + return c.Issue.HTMLURL(ctx) + c.hashLink(ctx) } // Link formats a relative URL-string to the issue-comment @@ -483,7 +483,7 @@ func (c *Comment) IssueURL(ctx context.Context) string { log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" } - return c.Issue.HTMLURL() + return c.Issue.HTMLURL(ctx) } // PRURL formats a URL-string to the pull-request @@ -503,7 +503,7 @@ func (c *Comment) PRURL(ctx context.Context) string { if !c.Issue.IsPull { return "" } - return c.Issue.HTMLURL() + return c.Issue.HTMLURL(ctx) } // CommentHashTag returns unique hash tag for comment id. diff --git a/models/issues/comment_test.go b/models/issues/comment_test.go index c08e3b970d3..3660f9c9398 100644 --- a/models/issues/comment_test.go +++ b/models/issues/comment_test.go @@ -24,7 +24,7 @@ func TestCreateComment(t *testing.T) { doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) now := time.Now().Unix() - comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{ + comment, err := issues_model.CreateComment(t.Context(), &issues_model.CreateCommentOptions{ Type: issues_model.CommentTypeComment, Doer: doer, Repo: repo, @@ -52,9 +52,9 @@ func Test_UpdateCommentAttachment(t *testing.T) { attachment := repo_model.Attachment{ Name: "test.txt", } - assert.NoError(t, db.Insert(db.DefaultContext, &attachment)) + assert.NoError(t, db.Insert(t.Context(), &attachment)) - err := issues_model.UpdateCommentAttachments(db.DefaultContext, comment, []string{attachment.UUID}) + err := issues_model.UpdateCommentAttachments(t.Context(), comment, []string{attachment.UUID}) assert.NoError(t, err) attachment2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{ID: attachment.ID}) @@ -68,7 +68,7 @@ func TestFetchCodeComments(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - res, err := issues_model.FetchCodeComments(db.DefaultContext, issue, user, false) + res, err := issues_model.FetchCodeComments(t.Context(), issue, user, false) assert.NoError(t, err) assert.Contains(t, res, "README.md") assert.Contains(t, res["README.md"], int64(4)) @@ -76,7 +76,7 @@ func TestFetchCodeComments(t *testing.T) { assert.Equal(t, int64(4), res["README.md"][4][0].ID) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - res, err = issues_model.FetchCodeComments(db.DefaultContext, issue, user2, false) + res, err = issues_model.FetchCodeComments(t.Context(), issue, user2, false) assert.NoError(t, err) assert.Len(t, res, 1) } @@ -92,7 +92,7 @@ func TestAsCommentType(t *testing.T) { func TestMigrate_InsertIssueComments(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) - _ = issue.LoadRepo(db.DefaultContext) + _ = issue.LoadRepo(t.Context()) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: issue.Repo.OwnerID}) reaction := &issues_model.Reaction{ Type: "heart", @@ -107,7 +107,7 @@ func TestMigrate_InsertIssueComments(t *testing.T) { Reactions: []*issues_model.Reaction{reaction}, } - err := issues_model.InsertIssueComments(db.DefaultContext, []*issues_model.Comment{comment}) + err := issues_model.InsertIssueComments(t.Context(), []*issues_model.Comment{comment}) assert.NoError(t, err) issueModified := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) @@ -120,7 +120,7 @@ func Test_UpdateIssueNumComments(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) - assert.NoError(t, issues_model.UpdateIssueNumComments(db.DefaultContext, issue2.ID)) + assert.NoError(t, issues_model.UpdateIssueNumComments(t.Context(), issue2.ID)) issue2 = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) assert.Equal(t, 1, issue2.NumComments) } diff --git a/models/issues/content_history_test.go b/models/issues/content_history_test.go index 1caa73a9487..d2fcc82b1d5 100644 --- a/models/issues/content_history_test.go +++ b/models/issues/content_history_test.go @@ -17,7 +17,7 @@ import ( func TestContentHistory(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - dbCtx := db.DefaultContext + dbCtx := t.Context() timeStampNow := timeutil.TimeStampNow() _ = issues_model.SaveIssueContentHistory(dbCtx, 1, 10, 0, timeStampNow, "i-a", true) @@ -82,18 +82,18 @@ func TestContentHistory(t *testing.T) { func TestHasIssueContentHistoryForCommentOnly(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - _ = db.TruncateBeans(db.DefaultContext, &issues_model.ContentHistory{}) + _ = db.TruncateBeans(t.Context(), &issues_model.ContentHistory{}) - hasHistory1, _ := issues_model.HasIssueContentHistory(db.DefaultContext, 10, 0) + hasHistory1, _ := issues_model.HasIssueContentHistory(t.Context(), 10, 0) assert.False(t, hasHistory1) - hasHistory2, _ := issues_model.HasIssueContentHistory(db.DefaultContext, 10, 100) + hasHistory2, _ := issues_model.HasIssueContentHistory(t.Context(), 10, 100) assert.False(t, hasHistory2) - _ = issues_model.SaveIssueContentHistory(db.DefaultContext, 1, 10, 100, timeutil.TimeStampNow(), "c-a", true) - _ = issues_model.SaveIssueContentHistory(db.DefaultContext, 1, 10, 100, timeutil.TimeStampNow().Add(5), "c-b", false) + _ = issues_model.SaveIssueContentHistory(t.Context(), 1, 10, 100, timeutil.TimeStampNow(), "c-a", true) + _ = issues_model.SaveIssueContentHistory(t.Context(), 1, 10, 100, timeutil.TimeStampNow().Add(5), "c-b", false) - hasHistory1, _ = issues_model.HasIssueContentHistory(db.DefaultContext, 10, 0) + hasHistory1, _ = issues_model.HasIssueContentHistory(t.Context(), 10, 0) assert.False(t, hasHistory1) - hasHistory2, _ = issues_model.HasIssueContentHistory(db.DefaultContext, 10, 100) + hasHistory2, _ = issues_model.HasIssueContentHistory(t.Context(), 10, 100) assert.True(t, hasHistory2) } diff --git a/models/issues/dependency_test.go b/models/issues/dependency_test.go index 67418039ded..0e6a870ff9e 100644 --- a/models/issues/dependency_test.go +++ b/models/issues/dependency_test.go @@ -6,7 +6,6 @@ package issues_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -18,56 +17,56 @@ func TestCreateIssueDependency(t *testing.T) { // Prepare assert.NoError(t, unittest.PrepareTestDatabase()) - user1, err := user_model.GetUserByID(db.DefaultContext, 1) + user1, err := user_model.GetUserByID(t.Context(), 1) assert.NoError(t, err) - issue1, err := issues_model.GetIssueByID(db.DefaultContext, 1) + issue1, err := issues_model.GetIssueByID(t.Context(), 1) assert.NoError(t, err) - issue2, err := issues_model.GetIssueByID(db.DefaultContext, 2) + issue2, err := issues_model.GetIssueByID(t.Context(), 2) assert.NoError(t, err) // Create a dependency and check if it was successful - err = issues_model.CreateIssueDependency(db.DefaultContext, user1, issue1, issue2) + err = issues_model.CreateIssueDependency(t.Context(), user1, issue1, issue2) assert.NoError(t, err) // Do it again to see if it will check if the dependency already exists - err = issues_model.CreateIssueDependency(db.DefaultContext, user1, issue1, issue2) + err = issues_model.CreateIssueDependency(t.Context(), user1, issue1, issue2) assert.Error(t, err) assert.True(t, issues_model.IsErrDependencyExists(err)) // Check for circular dependencies - err = issues_model.CreateIssueDependency(db.DefaultContext, user1, issue2, issue1) + err = issues_model.CreateIssueDependency(t.Context(), user1, issue2, issue1) assert.Error(t, err) assert.True(t, issues_model.IsErrCircularDependency(err)) _ = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeAddDependency, PosterID: user1.ID, IssueID: issue1.ID}) // Check if dependencies left is correct - left, err := issues_model.IssueNoDependenciesLeft(db.DefaultContext, issue1) + left, err := issues_model.IssueNoDependenciesLeft(t.Context(), issue1) assert.NoError(t, err) assert.False(t, left) // Close #2 and check again - _, err = issues_model.CloseIssue(db.DefaultContext, issue2, user1) + _, err = issues_model.CloseIssue(t.Context(), issue2, user1) assert.NoError(t, err) - issue2Closed, err := issues_model.GetIssueByID(db.DefaultContext, 2) + issue2Closed, err := issues_model.GetIssueByID(t.Context(), 2) assert.NoError(t, err) assert.True(t, issue2Closed.IsClosed) - left, err = issues_model.IssueNoDependenciesLeft(db.DefaultContext, issue1) + left, err = issues_model.IssueNoDependenciesLeft(t.Context(), issue1) assert.NoError(t, err) assert.True(t, left) // Test removing the dependency - err = issues_model.RemoveIssueDependency(db.DefaultContext, user1, issue1, issue2, issues_model.DependencyTypeBlockedBy) + err = issues_model.RemoveIssueDependency(t.Context(), user1, issue1, issue2, issues_model.DependencyTypeBlockedBy) assert.NoError(t, err) - _, err = issues_model.ReopenIssue(db.DefaultContext, issue2, user1) + _, err = issues_model.ReopenIssue(t.Context(), issue2, user1) assert.NoError(t, err) - issue2Reopened, err := issues_model.GetIssueByID(db.DefaultContext, 2) + issue2Reopened, err := issues_model.GetIssueByID(t.Context(), 2) assert.NoError(t, err) assert.False(t, issue2Reopened.IsClosed) } diff --git a/models/issues/issue.go b/models/issues/issue.go index ef651359ab9..053b96dceb5 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -405,14 +405,14 @@ func (issue *Issue) APIURL(ctx context.Context) string { } // HTMLURL returns the absolute URL to this issue. -func (issue *Issue) HTMLURL() string { +func (issue *Issue) HTMLURL(ctx context.Context) string { var path string if issue.IsPull { path = "pulls" } else { path = "issues" } - return fmt.Sprintf("%s/%s/%d", issue.Repo.HTMLURL(), path, issue.Index) + return fmt.Sprintf("%s/%s/%d", issue.Repo.HTMLURL(ctx), path, issue.Index) } // Link returns the issue's relative URL. diff --git a/models/issues/issue_label_test.go b/models/issues/issue_label_test.go index 0470b99e248..6ccf6debaea 100644 --- a/models/issues/issue_label_test.go +++ b/models/issues/issue_label_test.go @@ -6,7 +6,6 @@ package issues_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -22,7 +21,7 @@ func TestNewIssueLabelsScope(t *testing.T) { label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label2}, doer)) + assert.NoError(t, issues_model.NewIssueLabels(t.Context(), issue, []*issues_model.Label{label1, label2}, doer)) assert.Len(t, issue.Labels, 1) assert.Equal(t, label2.ID, issue.Labels[0].ID) diff --git a/models/issues/issue_list_test.go b/models/issues/issue_list_test.go index 5b4d2ca5ab9..e9dc412331d 100644 --- a/models/issues/issue_list_test.go +++ b/models/issues/issue_list_test.go @@ -6,7 +6,6 @@ package issues_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" @@ -23,7 +22,7 @@ func TestIssueList_LoadRepositories(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}), } - repos, err := issueList.LoadRepositories(db.DefaultContext) + repos, err := issueList.LoadRepositories(t.Context()) assert.NoError(t, err) assert.Len(t, repos, 2) for _, issue := range issueList { @@ -39,7 +38,7 @@ func TestIssueList_LoadAttributes(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}), } - assert.NoError(t, issueList.LoadAttributes(db.DefaultContext)) + assert.NoError(t, issueList.LoadAttributes(t.Context())) for _, issue := range issueList { assert.Equal(t, issue.RepoID, issue.Repo.ID) for _, label := range issue.Labels { diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go index 1c5db55bbca..09fd4926673 100644 --- a/models/issues/issue_test.go +++ b/models/issues/issue_test.go @@ -34,7 +34,7 @@ func TestIssue_ReplaceLabels(t *testing.T) { for i, labelID := range labelIDs { labels[i] = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: labelID, RepoID: repo.ID}) } - assert.NoError(t, issues_model.ReplaceIssueLabels(db.DefaultContext, issue, labels, doer)) + assert.NoError(t, issues_model.ReplaceIssueLabels(t.Context(), issue, labels, doer)) unittest.AssertCount(t, &issues_model.IssueLabel{IssueID: issueID}, len(expectedLabelIDs)) for _, labelID := range expectedLabelIDs { unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issueID, LabelID: labelID}) @@ -54,7 +54,7 @@ func TestIssue_ReplaceLabels(t *testing.T) { func Test_GetIssueIDsByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - ids, err := issues_model.GetIssueIDsByRepoID(db.DefaultContext, 1) + ids, err := issues_model.GetIssueIDsByRepoID(t.Context(), 1) assert.NoError(t, err) assert.Len(t, ids, 5) } @@ -62,16 +62,16 @@ func Test_GetIssueIDsByRepoID(t *testing.T) { func TestIssueAPIURL(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) - err := issue.LoadAttributes(db.DefaultContext) + err := issue.LoadAttributes(t.Context()) assert.NoError(t, err) - assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/issues/1", issue.APIURL(db.DefaultContext)) + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/issues/1", issue.APIURL(t.Context())) } func TestGetIssuesByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(expectedIssueIDs, nonExistentIssueIDs []int64) { - issues, err := issues_model.GetIssuesByIDs(db.DefaultContext, append(expectedIssueIDs, nonExistentIssueIDs...), true) + issues, err := issues_model.GetIssuesByIDs(t.Context(), append(expectedIssueIDs, nonExistentIssueIDs...), true) assert.NoError(t, err) actualIssueIDs := make([]int64, len(issues)) for i, issue := range issues { @@ -88,9 +88,9 @@ func TestGetParticipantIDsByIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) checkParticipants := func(issueID int64, userIDs []int) { - issue, err := issues_model.GetIssueByID(db.DefaultContext, issueID) + issue, err := issues_model.GetIssueByID(t.Context(), issueID) assert.NoError(t, err) - participants, err := issue.GetParticipantIDsByIssue(db.DefaultContext) + participants, err := issue.GetParticipantIDsByIssue(t.Context()) if assert.NoError(t, err) { participantsIDs := make([]int, len(participants)) for i, uid := range participants { @@ -122,7 +122,7 @@ func TestIssue_ClearLabels(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: test.issueID}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: test.doerID}) - assert.NoError(t, issues_model.ClearIssueLabels(db.DefaultContext, issue, doer)) + assert.NoError(t, issues_model.ClearIssueLabels(t.Context(), issue, doer)) unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: test.issueID}) } } @@ -138,7 +138,7 @@ func TestUpdateIssueCols(t *testing.T) { issue.Content = "This should have no effect" now := time.Now().Unix() - assert.NoError(t, issues_model.UpdateIssueCols(db.DefaultContext, issue, "name")) + assert.NoError(t, issues_model.UpdateIssueCols(t.Context(), issue, "name")) then := time.Now().Unix() updatedIssue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue.ID}) @@ -198,7 +198,7 @@ func TestIssues(t *testing.T) { []int64{2}, }, } { - issues, err := issues_model.Issues(db.DefaultContext, &test.Opts) + issues, err := issues_model.Issues(t.Context(), &test.Opts) assert.NoError(t, err) if assert.Len(t, issues, len(test.ExpectedIssueIDs)) { for i, issue := range issues { @@ -210,9 +210,9 @@ func TestIssues(t *testing.T) { func TestIssue_loadTotalTimes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - ms, err := issues_model.GetIssueByID(db.DefaultContext, 2) + ms, err := issues_model.GetIssueByID(t.Context(), 2) assert.NoError(t, err) - assert.NoError(t, ms.LoadTotalTimes(db.DefaultContext)) + assert.NoError(t, ms.LoadTotalTimes(t.Context())) assert.Equal(t, int64(3682), ms.TotalTrackedTime) } @@ -229,10 +229,10 @@ func testInsertIssue(t *testing.T, title, content string, expectIndex int64) *is Title: title, Content: content, } - err := issues_model.NewIssue(db.DefaultContext, repo, &issue, nil, nil) + err := issues_model.NewIssue(t.Context(), repo, &issue, nil, nil) assert.NoError(t, err) - has, err := db.GetEngine(db.DefaultContext).ID(issue.ID).Get(&newIssue) + has, err := db.GetEngine(t.Context()).ID(issue.ID).Get(&newIssue) assert.NoError(t, err) assert.True(t, has) assert.Equal(t, issue.Title, newIssue.Title) @@ -249,11 +249,11 @@ func TestIssue_InsertIssue(t *testing.T) { // there are 5 issues and max index is 5 on repository 1, so this one should 6 issue := testInsertIssue(t, "my issue1", "special issue's comments?", 6) - _, err := db.DeleteByID[issues_model.Issue](db.DefaultContext, issue.ID) + _, err := db.DeleteByID[issues_model.Issue](t.Context(), issue.ID) assert.NoError(t, err) issue = testInsertIssue(t, `my issue2, this is my son's love \n \r \ `, "special issue's '' comments?", 7) - _, err = db.DeleteByID[issues_model.Issue](db.DefaultContext, issue.ID) + _, err = db.DeleteByID[issues_model.Issue](t.Context(), issue.ID) assert.NoError(t, err) } @@ -265,7 +265,7 @@ func TestIssue_ResolveMentions(t *testing.T) { r := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: o.ID, LowerName: repo}) issue := &issues_model.Issue{RepoID: r.ID} d := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: doer}) - resolved, err := issues_model.ResolveIssueMentionsByVisibility(db.DefaultContext, issue, d, mentions) + resolved, err := issues_model.ResolveIssueMentionsByVisibility(t.Context(), issue, d, mentions) assert.NoError(t, err) ids := make([]int64, len(resolved)) for i, user := range resolved { @@ -345,7 +345,7 @@ func TestCorrectIssueStats(t *testing.T) { // Now we will call the GetIssueStats with these IDs and if working, // get the correct stats back. - issueStats, err := issues_model.GetIssueStats(db.DefaultContext, &issues_model.IssuesOptions{ + issueStats, err := issues_model.GetIssueStats(t.Context(), &issues_model.IssuesOptions{ RepoIDs: []int64{1}, IssueIDs: ids, }) @@ -361,7 +361,7 @@ func TestMilestoneList_LoadTotalTrackedTimes(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}), } - assert.NoError(t, miles.LoadTotalTrackedTimes(db.DefaultContext)) + assert.NoError(t, miles.LoadTotalTrackedTimes(t.Context())) assert.Equal(t, int64(3682), miles[0].TotalTrackedTime) } @@ -370,14 +370,14 @@ func TestLoadTotalTrackedTime(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) milestone := unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}) - assert.NoError(t, milestone.LoadTotalTrackedTime(db.DefaultContext)) + assert.NoError(t, milestone.LoadTotalTrackedTime(t.Context())) assert.Equal(t, int64(3682), milestone.TotalTrackedTime) } func TestCountIssues(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - count, err := issues_model.CountIssues(db.DefaultContext, &issues_model.IssuesOptions{}) + count, err := issues_model.CountIssues(t.Context(), &issues_model.IssuesOptions{}) assert.NoError(t, err) assert.EqualValues(t, 22, count) } @@ -392,7 +392,7 @@ func TestIssueLoadAttributes(t *testing.T) { } for _, issue := range issueList { - assert.NoError(t, issue.LoadAttributes(db.DefaultContext)) + assert.NoError(t, issue.LoadAttributes(t.Context())) assert.Equal(t, issue.RepoID, issue.Repo.ID) for _, label := range issue.Labels { assert.Equal(t, issue.RepoID, label.RepoID) @@ -453,7 +453,7 @@ func assertCreateIssues(t *testing.T, isPull bool) { Labels: []*issues_model.Label{label}, Reactions: []*issues_model.Reaction{reaction}, } - err := issues_model.InsertIssues(db.DefaultContext, is) + err := issues_model.InsertIssues(t.Context(), is) assert.NoError(t, err) i := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: title}) diff --git a/models/issues/issue_user_test.go b/models/issues/issue_user_test.go index 7c21aa15eef..ec6d85c2bb5 100644 --- a/models/issues/issue_user_test.go +++ b/models/issues/issue_user_test.go @@ -28,8 +28,8 @@ func Test_NewIssueUsers(t *testing.T) { } // artificially insert new issue - require.NoError(t, db.Insert(db.DefaultContext, newIssue)) - require.NoError(t, issues_model.NewIssueUsers(db.DefaultContext, repo, newIssue)) + require.NoError(t, db.Insert(t.Context(), newIssue)) + require.NoError(t, issues_model.NewIssueUsers(t.Context(), repo, newIssue)) // issue_user table should now have entries for new issue unittest.AssertExistsAndLoadBean(t, &issues_model.IssueUser{IssueID: newIssue.ID, UID: newIssue.PosterID}) @@ -40,13 +40,13 @@ func TestUpdateIssueUserByRead(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) - assert.NoError(t, issues_model.UpdateIssueUserByRead(db.DefaultContext, 4, issue.ID)) + assert.NoError(t, issues_model.UpdateIssueUserByRead(t.Context(), 4, issue.ID)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueUser{IssueID: issue.ID, UID: 4}, "is_read=1") - assert.NoError(t, issues_model.UpdateIssueUserByRead(db.DefaultContext, 4, issue.ID)) + assert.NoError(t, issues_model.UpdateIssueUserByRead(t.Context(), 4, issue.ID)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueUser{IssueID: issue.ID, UID: 4}, "is_read=1") - assert.NoError(t, issues_model.UpdateIssueUserByRead(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) + assert.NoError(t, issues_model.UpdateIssueUserByRead(t.Context(), unittest.NonexistentID, unittest.NonexistentID)) } func TestUpdateIssueUsersByMentions(t *testing.T) { @@ -54,7 +54,7 @@ func TestUpdateIssueUsersByMentions(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) uids := []int64{2, 5} - assert.NoError(t, issues_model.UpdateIssueUsersByMentions(db.DefaultContext, issue.ID, uids)) + assert.NoError(t, issues_model.UpdateIssueUsersByMentions(t.Context(), issue.ID, uids)) for _, uid := range uids { unittest.AssertExistsAndLoadBean(t, &issues_model.IssueUser{IssueID: issue.ID, UID: uid}, "is_mentioned=1") } diff --git a/models/issues/issue_watch_test.go b/models/issues/issue_watch_test.go index fad94e243e6..c860e8b8caf 100644 --- a/models/issues/issue_watch_test.go +++ b/models/issues/issue_watch_test.go @@ -16,11 +16,11 @@ import ( func TestCreateOrUpdateIssueWatch(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.NoError(t, issues_model.CreateOrUpdateIssueWatch(db.DefaultContext, 3, 1, true)) + assert.NoError(t, issues_model.CreateOrUpdateIssueWatch(t.Context(), 3, 1, true)) iw := unittest.AssertExistsAndLoadBean(t, &issues_model.IssueWatch{UserID: 3, IssueID: 1}) assert.True(t, iw.IsWatching) - assert.NoError(t, issues_model.CreateOrUpdateIssueWatch(db.DefaultContext, 1, 1, false)) + assert.NoError(t, issues_model.CreateOrUpdateIssueWatch(t.Context(), 1, 1, false)) iw = unittest.AssertExistsAndLoadBean(t, &issues_model.IssueWatch{UserID: 1, IssueID: 1}) assert.False(t, iw.IsWatching) } @@ -28,16 +28,16 @@ func TestCreateOrUpdateIssueWatch(t *testing.T) { func TestGetIssueWatch(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - _, exists, err := issues_model.GetIssueWatch(db.DefaultContext, 9, 1) + _, exists, err := issues_model.GetIssueWatch(t.Context(), 9, 1) assert.True(t, exists) assert.NoError(t, err) - iw, exists, err := issues_model.GetIssueWatch(db.DefaultContext, 2, 2) + iw, exists, err := issues_model.GetIssueWatch(t.Context(), 2, 2) assert.True(t, exists) assert.NoError(t, err) assert.False(t, iw.IsWatching) - _, exists, err = issues_model.GetIssueWatch(db.DefaultContext, 3, 1) + _, exists, err = issues_model.GetIssueWatch(t.Context(), 3, 1) assert.False(t, exists) assert.NoError(t, err) } @@ -45,22 +45,22 @@ func TestGetIssueWatch(t *testing.T) { func TestGetIssueWatchers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - iws, err := issues_model.GetIssueWatchers(db.DefaultContext, 1, db.ListOptions{}) + iws, err := issues_model.GetIssueWatchers(t.Context(), 1, db.ListOptions{}) assert.NoError(t, err) // Watcher is inactive, thus 0 assert.Empty(t, iws) - iws, err = issues_model.GetIssueWatchers(db.DefaultContext, 2, db.ListOptions{}) + iws, err = issues_model.GetIssueWatchers(t.Context(), 2, db.ListOptions{}) assert.NoError(t, err) // Watcher is explicit not watching assert.Empty(t, iws) - iws, err = issues_model.GetIssueWatchers(db.DefaultContext, 5, db.ListOptions{}) + iws, err = issues_model.GetIssueWatchers(t.Context(), 5, db.ListOptions{}) assert.NoError(t, err) // Issue has no Watchers assert.Empty(t, iws) - iws, err = issues_model.GetIssueWatchers(db.DefaultContext, 7, db.ListOptions{}) + iws, err = issues_model.GetIssueWatchers(t.Context(), 7, db.ListOptions{}) assert.NoError(t, err) // Issue has one watcher assert.Len(t, iws, 1) diff --git a/models/issues/issue_xref_test.go b/models/issues/issue_xref_test.go index 7f257330b76..b25a704bec2 100644 --- a/models/issues/issue_xref_test.go +++ b/models/issues/issue_xref_test.go @@ -83,7 +83,7 @@ func TestXRef_NeuterCrossReferences(t *testing.T) { d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) i.Title = "title2, no mentions" - assert.NoError(t, issues_model.ChangeIssueTitle(db.DefaultContext, i, d, title)) + assert.NoError(t, issues_model.ChangeIssueTitle(t.Context(), i, d, title)) ref = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: itarget.ID, RefIssueID: i.ID, RefCommentID: 0}) assert.Equal(t, issues_model.CommentTypeIssueRef, ref.Type) @@ -98,7 +98,7 @@ func TestXRef_ResolveCrossReferences(t *testing.T) { i1 := testCreateIssue(t, 1, 2, "title1", "content1", false) i2 := testCreateIssue(t, 1, 2, "title2", "content2", false) i3 := testCreateIssue(t, 1, 2, "title3", "content3", false) - _, err := issues_model.CloseIssue(db.DefaultContext, i3, d) + _, err := issues_model.CloseIssue(t.Context(), i3, d) assert.NoError(t, err) pr := testCreatePR(t, 1, 2, "titlepr", fmt.Sprintf("closes #%d", i1.Index)) @@ -118,7 +118,7 @@ func TestXRef_ResolveCrossReferences(t *testing.T) { c4 := testCreateComment(t, 2, pr.Issue.ID, fmt.Sprintf("closes #%d", i3.Index)) r4 := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: i3.ID, RefIssueID: pr.Issue.ID, RefCommentID: c4.ID}) - refs, err := pr.ResolveCrossReferences(db.DefaultContext) + refs, err := pr.ResolveCrossReferences(t.Context()) assert.NoError(t, err) assert.Len(t, refs, 3) assert.Equal(t, rp.ID, refs[0].ID, "bad ref rp: %+v", refs[0]) @@ -130,7 +130,7 @@ func testCreateIssue(t *testing.T, repo, doer int64, title, content string, ispu r := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo}) d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer}) - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) assert.NoError(t, err) defer committer.Close() @@ -163,7 +163,7 @@ func testCreatePR(t *testing.T, repo, doer int64, title, content string) *issues d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer}) i := &issues_model.Issue{RepoID: r.ID, PosterID: d.ID, Poster: d, Title: title, Content: content, IsPull: true} pr := &issues_model.PullRequest{HeadRepoID: repo, BaseRepoID: repo, HeadBranch: "head", BaseBranch: "base", Status: issues_model.PullRequestStatusMergeable} - assert.NoError(t, issues_model.NewPullRequest(db.DefaultContext, r, i, nil, nil, pr)) + assert.NoError(t, issues_model.NewPullRequest(t.Context(), r, i, nil, nil, pr)) pr.Issue = i return pr } @@ -173,7 +173,7 @@ func testCreateComment(t *testing.T, doer, issue int64, content string) *issues_ i := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue}) c := &issues_model.Comment{Type: issues_model.CommentTypeComment, PosterID: doer, Poster: d, IssueID: issue, Issue: i, Content: content} - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) assert.NoError(t, err) defer committer.Close() err = db.Insert(ctx, c) diff --git a/models/issues/label_test.go b/models/issues/label_test.go index 226036d5433..50393855d97 100644 --- a/models/issues/label_test.go +++ b/models/issues/label_test.go @@ -61,15 +61,15 @@ func TestNewLabels(t *testing.T) { {RepoID: 4, Name: "labelName4", Color: "ABCDEF"}, {RepoID: 5, Name: "labelName5", Color: "DEF"}, } - assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: ""})) - assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "#45G"})) - assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "#12345G"})) - assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "45G"})) - assert.Error(t, issues_model.NewLabel(db.DefaultContext, &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "12345G"})) + assert.Error(t, issues_model.NewLabel(t.Context(), &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: ""})) + assert.Error(t, issues_model.NewLabel(t.Context(), &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "#45G"})) + assert.Error(t, issues_model.NewLabel(t.Context(), &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "#12345G"})) + assert.Error(t, issues_model.NewLabel(t.Context(), &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "45G"})) + assert.Error(t, issues_model.NewLabel(t.Context(), &issues_model.Label{RepoID: 3, Name: "invalid Color", Color: "12345G"})) for _, label := range labels { unittest.AssertNotExistsBean(t, label) } - assert.NoError(t, issues_model.NewLabels(db.DefaultContext, labels...)) + assert.NoError(t, issues_model.NewLabels(t.Context(), labels...)) for _, label := range labels { unittest.AssertExistsAndLoadBean(t, label, unittest.Cond("id = ?", label.ID)) } @@ -78,31 +78,31 @@ func TestNewLabels(t *testing.T) { func TestGetLabelByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - label, err := issues_model.GetLabelByID(db.DefaultContext, 1) + label, err := issues_model.GetLabelByID(t.Context(), 1) assert.NoError(t, err) assert.EqualValues(t, 1, label.ID) - _, err = issues_model.GetLabelByID(db.DefaultContext, unittest.NonexistentID) + _, err = issues_model.GetLabelByID(t.Context(), unittest.NonexistentID) assert.True(t, issues_model.IsErrLabelNotExist(err)) } func TestGetLabelInRepoByName(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - label, err := issues_model.GetLabelInRepoByName(db.DefaultContext, 1, "label1") + label, err := issues_model.GetLabelInRepoByName(t.Context(), 1, "label1") assert.NoError(t, err) assert.EqualValues(t, 1, label.ID) assert.Equal(t, "label1", label.Name) - _, err = issues_model.GetLabelInRepoByName(db.DefaultContext, 1, "") + _, err = issues_model.GetLabelInRepoByName(t.Context(), 1, "") assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) - _, err = issues_model.GetLabelInRepoByName(db.DefaultContext, unittest.NonexistentID, "nonexistent") + _, err = issues_model.GetLabelInRepoByName(t.Context(), unittest.NonexistentID, "nonexistent") assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) } func TestGetLabelInRepoByNames(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labelIDs, err := issues_model.GetLabelIDsInRepoByNames(db.DefaultContext, 1, []string{"label1", "label2"}) + labelIDs, err := issues_model.GetLabelIDsInRepoByNames(t.Context(), 1, []string{"label1", "label2"}) assert.NoError(t, err) assert.Len(t, labelIDs, 2) @@ -114,7 +114,7 @@ func TestGetLabelInRepoByNames(t *testing.T) { func TestGetLabelInRepoByNamesDiscardsNonExistentLabels(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // label3 doesn't exists.. See labels.yml - labelIDs, err := issues_model.GetLabelIDsInRepoByNames(db.DefaultContext, 1, []string{"label1", "label2", "label3"}) + labelIDs, err := issues_model.GetLabelIDsInRepoByNames(t.Context(), 1, []string{"label1", "label2", "label3"}) assert.NoError(t, err) assert.Len(t, labelIDs, 2) @@ -126,20 +126,20 @@ func TestGetLabelInRepoByNamesDiscardsNonExistentLabels(t *testing.T) { func TestGetLabelInRepoByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - label, err := issues_model.GetLabelInRepoByID(db.DefaultContext, 1, 1) + label, err := issues_model.GetLabelInRepoByID(t.Context(), 1, 1) assert.NoError(t, err) assert.EqualValues(t, 1, label.ID) - _, err = issues_model.GetLabelInRepoByID(db.DefaultContext, 1, -1) + _, err = issues_model.GetLabelInRepoByID(t.Context(), 1, -1) assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) - _, err = issues_model.GetLabelInRepoByID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) + _, err = issues_model.GetLabelInRepoByID(t.Context(), unittest.NonexistentID, unittest.NonexistentID) assert.True(t, issues_model.IsErrRepoLabelNotExist(err)) } func TestGetLabelsInRepoByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labels, err := issues_model.GetLabelsInRepoByIDs(db.DefaultContext, 1, []int64{1, 2, unittest.NonexistentID}) + labels, err := issues_model.GetLabelsInRepoByIDs(t.Context(), 1, []int64{1, 2, unittest.NonexistentID}) assert.NoError(t, err) if assert.Len(t, labels, 2) { assert.EqualValues(t, 1, labels[0].ID) @@ -150,7 +150,7 @@ func TestGetLabelsInRepoByIDs(t *testing.T) { func TestGetLabelsByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(repoID int64, sortType string, expectedIssueIDs []int64) { - labels, err := issues_model.GetLabelsByRepoID(db.DefaultContext, repoID, sortType, db.ListOptions{}) + labels, err := issues_model.GetLabelsByRepoID(t.Context(), repoID, sortType, db.ListOptions{}) assert.NoError(t, err) assert.Len(t, labels, len(expectedIssueIDs)) for i, label := range labels { @@ -167,46 +167,46 @@ func TestGetLabelsByRepoID(t *testing.T) { func TestGetLabelInOrgByName(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - label, err := issues_model.GetLabelInOrgByName(db.DefaultContext, 3, "orglabel3") + label, err := issues_model.GetLabelInOrgByName(t.Context(), 3, "orglabel3") assert.NoError(t, err) assert.EqualValues(t, 3, label.ID) assert.Equal(t, "orglabel3", label.Name) - _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, 3, "") + _, err = issues_model.GetLabelInOrgByName(t.Context(), 3, "") assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) - _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, 0, "orglabel3") + _, err = issues_model.GetLabelInOrgByName(t.Context(), 0, "orglabel3") assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) - _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, -1, "orglabel3") + _, err = issues_model.GetLabelInOrgByName(t.Context(), -1, "orglabel3") assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) - _, err = issues_model.GetLabelInOrgByName(db.DefaultContext, unittest.NonexistentID, "nonexistent") + _, err = issues_model.GetLabelInOrgByName(t.Context(), unittest.NonexistentID, "nonexistent") assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) } func TestGetLabelInOrgByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - label, err := issues_model.GetLabelInOrgByID(db.DefaultContext, 3, 3) + label, err := issues_model.GetLabelInOrgByID(t.Context(), 3, 3) assert.NoError(t, err) assert.EqualValues(t, 3, label.ID) - _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, 3, -1) + _, err = issues_model.GetLabelInOrgByID(t.Context(), 3, -1) assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) - _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, 0, 3) + _, err = issues_model.GetLabelInOrgByID(t.Context(), 0, 3) assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) - _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, -1, 3) + _, err = issues_model.GetLabelInOrgByID(t.Context(), -1, 3) assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) - _, err = issues_model.GetLabelInOrgByID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) + _, err = issues_model.GetLabelInOrgByID(t.Context(), unittest.NonexistentID, unittest.NonexistentID) assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) } func TestGetLabelsInOrgByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labels, err := issues_model.GetLabelsInOrgByIDs(db.DefaultContext, 3, []int64{3, 4, unittest.NonexistentID}) + labels, err := issues_model.GetLabelsInOrgByIDs(t.Context(), 3, []int64{3, 4, unittest.NonexistentID}) assert.NoError(t, err) if assert.Len(t, labels, 2) { assert.EqualValues(t, 3, labels[0].ID) @@ -217,7 +217,7 @@ func TestGetLabelsInOrgByIDs(t *testing.T) { func TestGetLabelsByOrgID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(orgID int64, sortType string, expectedIssueIDs []int64) { - labels, err := issues_model.GetLabelsByOrgID(db.DefaultContext, orgID, sortType, db.ListOptions{}) + labels, err := issues_model.GetLabelsByOrgID(t.Context(), orgID, sortType, db.ListOptions{}) assert.NoError(t, err) assert.Len(t, labels, len(expectedIssueIDs)) for i, label := range labels { @@ -229,10 +229,10 @@ func TestGetLabelsByOrgID(t *testing.T) { testSuccess(3, "reversealphabetically", []int64{4, 3}) testSuccess(3, "default", []int64{3, 4}) - _, err := issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{}) + _, err := issues_model.GetLabelsByOrgID(t.Context(), 0, "leastissues", db.ListOptions{}) assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) - _, err = issues_model.GetLabelsByOrgID(db.DefaultContext, -1, "leastissues", db.ListOptions{}) + _, err = issues_model.GetLabelsByOrgID(t.Context(), -1, "leastissues", db.ListOptions{}) assert.True(t, issues_model.IsErrOrgLabelNotExist(err)) } @@ -240,13 +240,13 @@ func TestGetLabelsByOrgID(t *testing.T) { func TestGetLabelsByIssueID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - labels, err := issues_model.GetLabelsByIssueID(db.DefaultContext, 1) + labels, err := issues_model.GetLabelsByIssueID(t.Context(), 1) assert.NoError(t, err) if assert.Len(t, labels, 1) { assert.EqualValues(t, 1, labels[0].ID) } - labels, err = issues_model.GetLabelsByIssueID(db.DefaultContext, unittest.NonexistentID) + labels, err = issues_model.GetLabelsByIssueID(t.Context(), unittest.NonexistentID) assert.NoError(t, err) assert.Empty(t, labels) } @@ -265,7 +265,7 @@ func TestUpdateLabel(t *testing.T) { } label.Color = update.Color label.Name = update.Name - assert.NoError(t, issues_model.UpdateLabel(db.DefaultContext, update)) + assert.NoError(t, issues_model.UpdateLabel(t.Context(), update)) newLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) assert.Equal(t, label.ID, newLabel.ID) assert.Equal(t, label.Color, newLabel.Color) @@ -278,21 +278,21 @@ func TestUpdateLabel(t *testing.T) { func TestDeleteLabel(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1}) - assert.NoError(t, issues_model.DeleteLabel(db.DefaultContext, label.RepoID, label.ID)) + assert.NoError(t, issues_model.DeleteLabel(t.Context(), label.RepoID, label.ID)) unittest.AssertNotExistsBean(t, &issues_model.Label{ID: label.ID, RepoID: label.RepoID}) - assert.NoError(t, issues_model.DeleteLabel(db.DefaultContext, label.RepoID, label.ID)) + assert.NoError(t, issues_model.DeleteLabel(t.Context(), label.RepoID, label.ID)) unittest.AssertNotExistsBean(t, &issues_model.Label{ID: label.ID}) - assert.NoError(t, issues_model.DeleteLabel(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) + assert.NoError(t, issues_model.DeleteLabel(t.Context(), unittest.NonexistentID, unittest.NonexistentID)) unittest.CheckConsistencyFor(t, &issues_model.Label{}, &repo_model.Repository{}) } func TestHasIssueLabel(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.True(t, issues_model.HasIssueLabel(db.DefaultContext, 1, 1)) - assert.False(t, issues_model.HasIssueLabel(db.DefaultContext, 1, 2)) - assert.False(t, issues_model.HasIssueLabel(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) + assert.True(t, issues_model.HasIssueLabel(t.Context(), 1, 1)) + assert.False(t, issues_model.HasIssueLabel(t.Context(), 1, 2)) + assert.False(t, issues_model.HasIssueLabel(t.Context(), unittest.NonexistentID, unittest.NonexistentID)) } func TestNewIssueLabel(t *testing.T) { @@ -303,7 +303,7 @@ func TestNewIssueLabel(t *testing.T) { // add new IssueLabel prevNumIssues := label.NumIssues - assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer)) + assert.NoError(t, issues_model.NewIssueLabel(t.Context(), issue, label, doer)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ Type: issues_model.CommentTypeLabel, @@ -316,7 +316,7 @@ func TestNewIssueLabel(t *testing.T) { assert.Equal(t, prevNumIssues+1, label.NumIssues) // re-add existing IssueLabel - assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer)) + assert.NoError(t, issues_model.NewIssueLabel(t.Context(), issue, label, doer)) unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{}) } @@ -330,19 +330,19 @@ func TestNewIssueExclusiveLabel(t *testing.T) { exclusiveLabelB := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8}) // coexisting regular and exclusive label - assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, otherLabel, doer)) - assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelA, doer)) + assert.NoError(t, issues_model.NewIssueLabel(t.Context(), issue, otherLabel, doer)) + assert.NoError(t, issues_model.NewIssueLabel(t.Context(), issue, exclusiveLabelA, doer)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) // exclusive label replaces existing one - assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelB, doer)) + assert.NoError(t, issues_model.NewIssueLabel(t.Context(), issue, exclusiveLabelB, doer)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID}) unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) // exclusive label replaces existing one again - assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelA, doer)) + assert.NoError(t, issues_model.NewIssueLabel(t.Context(), issue, exclusiveLabelA, doer)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID}) @@ -355,7 +355,7 @@ func TestNewIssueLabels(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 5}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label2}, doer)) + assert.NoError(t, issues_model.NewIssueLabels(t.Context(), issue, []*issues_model.Label{label1, label2}, doer)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label1.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ Type: issues_model.CommentTypeLabel, @@ -373,7 +373,7 @@ func TestNewIssueLabels(t *testing.T) { assert.Equal(t, 1, label2.NumClosedIssues) // corner case: test empty slice - assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{}, doer)) + assert.NoError(t, issues_model.NewIssueLabels(t.Context(), issue, []*issues_model.Label{}, doer)) unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{}) } @@ -394,7 +394,7 @@ func TestDeleteIssueLabel(t *testing.T) { } } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(t.Context()) defer committer.Close() assert.NoError(t, err) assert.NoError(t, issues_model.DeleteIssueLabel(ctx, issue, label, doer)) diff --git a/models/issues/milestone_test.go b/models/issues/milestone_test.go index f73355c27d9..107ad305d48 100644 --- a/models/issues/milestone_test.go +++ b/models/issues/milestone_test.go @@ -27,12 +27,12 @@ func TestMilestone_State(t *testing.T) { func TestGetMilestoneByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - milestone, err := issues_model.GetMilestoneByRepoID(db.DefaultContext, 1, 1) + milestone, err := issues_model.GetMilestoneByRepoID(t.Context(), 1, 1) assert.NoError(t, err) assert.EqualValues(t, 1, milestone.ID) assert.EqualValues(t, 1, milestone.RepoID) - _, err = issues_model.GetMilestoneByRepoID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) + _, err = issues_model.GetMilestoneByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID) assert.True(t, issues_model.IsErrMilestoneNotExist(err)) } @@ -45,7 +45,7 @@ func TestGetMilestonesByRepoID(t *testing.T) { isClosed = optional.Some(state == api.StateClosed) } repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) - milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + milestones, err := db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: repo.ID, IsClosed: isClosed, }) @@ -82,7 +82,7 @@ func TestGetMilestonesByRepoID(t *testing.T) { test(3, api.StateClosed) test(3, api.StateAll) - milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + milestones, err := db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: unittest.NonexistentID, IsClosed: optional.Some(false), }) @@ -95,7 +95,7 @@ func TestGetMilestones(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) test := func(sortType string, sortCond func(*issues_model.Milestone) int) { for _, page := range []int{0, 1} { - milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + milestones, err := db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: setting.UI.IssuePagingNum, @@ -112,7 +112,7 @@ func TestGetMilestones(t *testing.T) { } assert.True(t, sort.IntsAreSorted(values)) - milestones, err = db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + milestones, err = db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: setting.UI.IssuePagingNum, @@ -155,7 +155,7 @@ func TestCountRepoMilestones(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(repoID int64) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) - count, err := db.Count[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + count, err := db.Count[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: repoID, }) assert.NoError(t, err) @@ -165,7 +165,7 @@ func TestCountRepoMilestones(t *testing.T) { test(2) test(3) - count, err := db.Count[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + count, err := db.Count[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: unittest.NonexistentID, }) assert.NoError(t, err) @@ -176,7 +176,7 @@ func TestCountRepoClosedMilestones(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(repoID int64) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) - count, err := db.Count[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + count, err := db.Count[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: repoID, IsClosed: optional.Some(true), }) @@ -187,7 +187,7 @@ func TestCountRepoClosedMilestones(t *testing.T) { test(2) test(3) - count, err := db.Count[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + count, err := db.Count[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: unittest.NonexistentID, IsClosed: optional.Some(true), }) @@ -204,7 +204,7 @@ func TestCountMilestonesByRepoIDs(t *testing.T) { repo1OpenCount, repo1ClosedCount := milestonesCount(1) repo2OpenCount, repo2ClosedCount := milestonesCount(2) - openCounts, err := issues_model.CountMilestonesMap(db.DefaultContext, issues_model.FindMilestoneOptions{ + openCounts, err := issues_model.CountMilestonesMap(t.Context(), issues_model.FindMilestoneOptions{ RepoIDs: []int64{1, 2}, IsClosed: optional.Some(false), }) @@ -212,7 +212,7 @@ func TestCountMilestonesByRepoIDs(t *testing.T) { assert.EqualValues(t, repo1OpenCount, openCounts[1]) assert.EqualValues(t, repo2OpenCount, openCounts[2]) - closedCounts, err := issues_model.CountMilestonesMap(db.DefaultContext, + closedCounts, err := issues_model.CountMilestonesMap(t.Context(), issues_model.FindMilestoneOptions{ RepoIDs: []int64{1, 2}, IsClosed: optional.Some(true), @@ -228,7 +228,7 @@ func TestGetMilestonesByRepoIDs(t *testing.T) { repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) test := func(sortType string, sortCond func(*issues_model.Milestone) int) { for _, page := range []int{0, 1} { - openMilestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + openMilestones, err := db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: setting.UI.IssuePagingNum, @@ -245,7 +245,7 @@ func TestGetMilestonesByRepoIDs(t *testing.T) { } assert.True(t, sort.IntsAreSorted(values)) - closedMilestones, err := db.Find[issues_model.Milestone](db.DefaultContext, + closedMilestones, err := db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ ListOptions: db.ListOptions{ Page: page, @@ -292,7 +292,7 @@ func TestNewMilestone(t *testing.T) { Content: "milestoneContent", } - assert.NoError(t, issues_model.NewMilestone(db.DefaultContext, milestone)) + assert.NoError(t, issues_model.NewMilestone(t.Context(), milestone)) unittest.AssertExistsAndLoadBean(t, milestone) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{}) } @@ -301,22 +301,22 @@ func TestChangeMilestoneStatus(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) milestone := unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}) - assert.NoError(t, issues_model.ChangeMilestoneStatus(db.DefaultContext, milestone, true)) + assert.NoError(t, issues_model.ChangeMilestoneStatus(t.Context(), milestone, true)) unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}, "is_closed=1") unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{}) - assert.NoError(t, issues_model.ChangeMilestoneStatus(db.DefaultContext, milestone, false)) + assert.NoError(t, issues_model.ChangeMilestoneStatus(t.Context(), milestone, false)) unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}, "is_closed=0") unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: milestone.RepoID}, &issues_model.Milestone{}) } func TestDeleteMilestoneByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.NoError(t, issues_model.DeleteMilestoneByRepoID(db.DefaultContext, 1, 1)) + assert.NoError(t, issues_model.DeleteMilestoneByRepoID(t.Context(), 1, 1)) unittest.AssertNotExistsBean(t, &issues_model.Milestone{ID: 1}) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: 1}) - assert.NoError(t, issues_model.DeleteMilestoneByRepoID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) + assert.NoError(t, issues_model.DeleteMilestoneByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID)) } func TestUpdateMilestone(t *testing.T) { @@ -325,7 +325,7 @@ func TestUpdateMilestone(t *testing.T) { milestone := unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}) milestone.Name = " newMilestoneName " milestone.Content = "newMilestoneContent" - assert.NoError(t, issues_model.UpdateMilestone(db.DefaultContext, milestone, milestone.IsClosed)) + assert.NoError(t, issues_model.UpdateMilestone(t.Context(), milestone, milestone.IsClosed)) milestone = unittest.AssertExistsAndLoadBean(t, &issues_model.Milestone{ID: 1}) assert.Equal(t, "newMilestoneName", milestone.Name) unittest.CheckConsistencyFor(t, &issues_model.Milestone{}) @@ -338,16 +338,16 @@ func TestUpdateMilestoneCounters(t *testing.T) { issue.IsClosed = true issue.ClosedUnix = timeutil.TimeStampNow() - _, err := db.GetEngine(db.DefaultContext).ID(issue.ID).Cols("is_closed", "closed_unix").Update(issue) + _, err := db.GetEngine(t.Context()).ID(issue.ID).Cols("is_closed", "closed_unix").Update(issue) assert.NoError(t, err) - assert.NoError(t, issues_model.UpdateMilestoneCounters(db.DefaultContext, issue.MilestoneID)) + assert.NoError(t, issues_model.UpdateMilestoneCounters(t.Context(), issue.MilestoneID)) unittest.CheckConsistencyFor(t, &issues_model.Milestone{}) issue.IsClosed = false issue.ClosedUnix = 0 - _, err = db.GetEngine(db.DefaultContext).ID(issue.ID).Cols("is_closed", "closed_unix").Update(issue) + _, err = db.GetEngine(t.Context()).ID(issue.ID).Cols("is_closed", "closed_unix").Update(issue) assert.NoError(t, err) - assert.NoError(t, issues_model.UpdateMilestoneCounters(db.DefaultContext, issue.MilestoneID)) + assert.NoError(t, issues_model.UpdateMilestoneCounters(t.Context(), issue.MilestoneID)) unittest.CheckConsistencyFor(t, &issues_model.Milestone{}) } @@ -360,7 +360,7 @@ func TestMigrate_InsertMilestones(t *testing.T) { RepoID: repo.ID, Name: name, } - err := issues_model.InsertMilestones(db.DefaultContext, ms) + err := issues_model.InsertMilestones(t.Context(), ms) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, ms) repoModified := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}) diff --git a/models/issues/pull.go b/models/issues/pull.go index 00d7bfe1cab..7a37b627e1b 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -29,6 +29,8 @@ import ( var ErrMustCollaborator = util.NewPermissionDeniedErrorf("user must be a collaborator") +const reviewedBy = "Reviewed-by: " + // ErrPullRequestNotExist represents a "PullRequestNotExist" kind of error. type ErrPullRequestNotExist struct { ID int64 @@ -348,7 +350,11 @@ type ReviewCount struct { func (pr *PullRequest) GetApprovalCounts(ctx context.Context) ([]*ReviewCount, error) { rCounts := make([]*ReviewCount, 0, 6) sess := db.GetEngine(ctx).Where("issue_id = ?", pr.IssueID) - return rCounts, sess.Select("issue_id, type, count(id) as `count`").Where("official = ? AND dismissed = ?", true, false).GroupBy("issue_id, type").Table("review").Find(&rCounts) + return rCounts, sess.Select("issue_id, type, count(id) as `count`"). + Where(builder.Eq{"official": true, "dismissed": false}). + GroupBy("issue_id, type"). + Table("review"). + Find(&rCounts) } // GetApprovers returns the approvers of the pull request @@ -392,7 +398,7 @@ func (pr *PullRequest) getReviewedByLines(ctx context.Context, writer io.Writer) } else if review.Reviewer == nil { continue } - if _, err := writer.Write([]byte("Reviewed-by: ")); err != nil { + if _, err := writer.Write([]byte(reviewedBy)); err != nil { return err } if _, err := writer.Write([]byte(review.Reviewer.NewGitSig().String())); err != nil { diff --git a/models/issues/pull_list_test.go b/models/issues/pull_list_test.go index feb59df2160..a219603c902 100644 --- a/models/issues/pull_list_test.go +++ b/models/issues/pull_list_test.go @@ -6,7 +6,6 @@ package issues_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" @@ -20,13 +19,13 @@ func TestPullRequestList_LoadAttributes(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}), unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}), } - assert.NoError(t, prs.LoadAttributes(db.DefaultContext)) + assert.NoError(t, prs.LoadAttributes(t.Context())) for _, pr := range prs { assert.NotNil(t, pr.Issue) assert.Equal(t, pr.IssueID, pr.Issue.ID) } - assert.NoError(t, issues_model.PullRequestList([]*issues_model.PullRequest{}).LoadAttributes(db.DefaultContext)) + assert.NoError(t, issues_model.PullRequestList([]*issues_model.PullRequest{}).LoadAttributes(t.Context())) } func TestPullRequestList_LoadReviewCommentsCounts(t *testing.T) { @@ -36,7 +35,7 @@ func TestPullRequestList_LoadReviewCommentsCounts(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}), unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}), } - reviewComments, err := prs.LoadReviewCommentsCounts(db.DefaultContext) + reviewComments, err := prs.LoadReviewCommentsCounts(t.Context()) assert.NoError(t, err) assert.Len(t, reviewComments, 2) assert.Equal(t, 1, reviewComments[prs[0].IssueID]) @@ -50,7 +49,7 @@ func TestPullRequestList_LoadReviews(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}), unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}), } - reviewList, err := prs.LoadReviews(db.DefaultContext) + reviewList, err := prs.LoadReviews(t.Context()) assert.NoError(t, err) // 1, 7, 8, 9, 10, 22 assert.Len(t, reviewList, 6) diff --git a/models/issues/pull_test.go b/models/issues/pull_test.go index 39efaa5792f..7089af253b7 100644 --- a/models/issues/pull_test.go +++ b/models/issues/pull_test.go @@ -20,7 +20,7 @@ import ( func TestPullRequest_LoadAttributes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) + assert.NoError(t, pr.LoadAttributes(t.Context())) assert.NotNil(t, pr.Merger) assert.Equal(t, pr.MergerID, pr.Merger.ID) } @@ -28,10 +28,10 @@ func TestPullRequest_LoadAttributes(t *testing.T) { func TestPullRequest_LoadIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadIssue(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(t.Context())) assert.NotNil(t, pr.Issue) assert.Equal(t, int64(2), pr.Issue.ID) - assert.NoError(t, pr.LoadIssue(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(t.Context())) assert.NotNil(t, pr.Issue) assert.Equal(t, int64(2), pr.Issue.ID) } @@ -39,10 +39,10 @@ func TestPullRequest_LoadIssue(t *testing.T) { func TestPullRequest_LoadBaseRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadBaseRepo(t.Context())) assert.NotNil(t, pr.BaseRepo) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) - assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadBaseRepo(t.Context())) assert.NotNil(t, pr.BaseRepo) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) } @@ -50,7 +50,7 @@ func TestPullRequest_LoadBaseRepo(t *testing.T) { func TestPullRequest_LoadHeadRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadHeadRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadHeadRepo(t.Context())) assert.NotNil(t, pr.HeadRepo) assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID) } @@ -61,7 +61,7 @@ func TestPullRequest_LoadHeadRepo(t *testing.T) { func TestPullRequestsNewest(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - prs, count, err := issues_model.PullRequests(db.DefaultContext, 1, &issues_model.PullRequestsOptions{ + prs, count, err := issues_model.PullRequests(t.Context(), 1, &issues_model.PullRequestsOptions{ ListOptions: db.ListOptions{ Page: 1, }, @@ -91,16 +91,16 @@ func TestPullRequests_Closed_RecentSortType(t *testing.T) { } assert.NoError(t, unittest.PrepareTestDatabase()) - _, err := db.Exec(db.DefaultContext, "UPDATE issue SET closed_unix = 1707270001, updated_unix = 1707270001, is_closed = true WHERE id = 2") + _, err := db.Exec(t.Context(), "UPDATE issue SET closed_unix = 1707270001, updated_unix = 1707270001, is_closed = true WHERE id = 2") require.NoError(t, err) - _, err = db.Exec(db.DefaultContext, "UPDATE issue SET closed_unix = 1707271000, updated_unix = 1707279999, is_closed = true WHERE id = 3") + _, err = db.Exec(t.Context(), "UPDATE issue SET closed_unix = 1707271000, updated_unix = 1707279999, is_closed = true WHERE id = 3") require.NoError(t, err) - _, err = db.Exec(db.DefaultContext, "UPDATE issue SET closed_unix = 1707279999, updated_unix = 1707275555, is_closed = true WHERE id = 11") + _, err = db.Exec(t.Context(), "UPDATE issue SET closed_unix = 1707279999, updated_unix = 1707275555, is_closed = true WHERE id = 11") require.NoError(t, err) for _, test := range tests { t.Run(test.sortType, func(t *testing.T) { - prs, _, err := issues_model.PullRequests(db.DefaultContext, 1, &issues_model.PullRequestsOptions{ + prs, _, err := issues_model.PullRequests(t.Context(), 1, &issues_model.PullRequestsOptions{ ListOptions: db.ListOptions{ Page: 1, }, @@ -122,33 +122,33 @@ func TestLoadRequestedReviewers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - assert.NoError(t, pull.LoadIssue(db.DefaultContext)) + assert.NoError(t, pull.LoadIssue(t.Context())) issue := pull.Issue - assert.NoError(t, issue.LoadRepo(db.DefaultContext)) + assert.NoError(t, issue.LoadRepo(t.Context())) assert.Empty(t, pull.RequestedReviewers) - user1, err := user_model.GetUserByID(db.DefaultContext, 1) + user1, err := user_model.GetUserByID(t.Context(), 1) assert.NoError(t, err) - comment, err := issues_model.AddReviewRequest(db.DefaultContext, issue, user1, &user_model.User{}) + comment, err := issues_model.AddReviewRequest(t.Context(), issue, user1, &user_model.User{}) assert.NoError(t, err) assert.NotNil(t, comment) - assert.NoError(t, pull.LoadRequestedReviewers(db.DefaultContext)) + assert.NoError(t, pull.LoadRequestedReviewers(t.Context())) assert.Len(t, pull.RequestedReviewers, 6) - comment, err = issues_model.RemoveReviewRequest(db.DefaultContext, issue, user1, &user_model.User{}) + comment, err = issues_model.RemoveReviewRequest(t.Context(), issue, user1, &user_model.User{}) assert.NoError(t, err) assert.NotNil(t, comment) pull.RequestedReviewers = nil - assert.NoError(t, pull.LoadRequestedReviewers(db.DefaultContext)) + assert.NoError(t, pull.LoadRequestedReviewers(t.Context())) assert.Empty(t, pull.RequestedReviewers) } func TestPullRequestsOldest(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - prs, count, err := issues_model.PullRequests(db.DefaultContext, 1, &issues_model.PullRequestsOptions{ + prs, count, err := issues_model.PullRequests(t.Context(), 1, &issues_model.PullRequestsOptions{ ListOptions: db.ListOptions{ Page: 1, }, @@ -166,11 +166,11 @@ func TestPullRequestsOldest(t *testing.T) { func TestGetUnmergedPullRequest(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(t.Context(), 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) assert.NoError(t, err) assert.Equal(t, int64(2), pr.ID) - _, err = issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub) + _, err = issues_model.GetUnmergedPullRequest(t.Context(), 1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub) assert.Error(t, err) assert.True(t, issues_model.IsErrPullRequestNotExist(err)) } @@ -178,18 +178,18 @@ func TestGetUnmergedPullRequest(t *testing.T) { func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "branch2") + exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(t.Context(), 1, "branch2") assert.NoError(t, err) assert.True(t, exist) - exist, err = issues_model.HasUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "not_exist_branch") + exist, err = issues_model.HasUnmergedPullRequestsByHeadInfo(t.Context(), 1, "not_exist_branch") assert.NoError(t, err) assert.False(t, exist) } func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "branch2") + prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(t.Context(), 1, "branch2") assert.NoError(t, err) assert.Len(t, prs, 1) for _, pr := range prs { @@ -200,7 +200,7 @@ func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) { func TestGetUnmergedPullRequestsByBaseInfo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(db.DefaultContext, 1, "master") + prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(t.Context(), 1, "master") assert.NoError(t, err) assert.Len(t, prs, 1) pr := prs[0] @@ -211,39 +211,39 @@ func TestGetUnmergedPullRequestsByBaseInfo(t *testing.T) { func TestGetPullRequestByIndex(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetPullRequestByIndex(db.DefaultContext, 1, 2) + pr, err := issues_model.GetPullRequestByIndex(t.Context(), 1, 2) assert.NoError(t, err) assert.Equal(t, int64(1), pr.BaseRepoID) assert.Equal(t, int64(2), pr.Index) - _, err = issues_model.GetPullRequestByIndex(db.DefaultContext, 9223372036854775807, 9223372036854775807) + _, err = issues_model.GetPullRequestByIndex(t.Context(), 9223372036854775807, 9223372036854775807) assert.Error(t, err) assert.True(t, issues_model.IsErrPullRequestNotExist(err)) - _, err = issues_model.GetPullRequestByIndex(db.DefaultContext, 1, 0) + _, err = issues_model.GetPullRequestByIndex(t.Context(), 1, 0) assert.Error(t, err) assert.True(t, issues_model.IsErrPullRequestNotExist(err)) } func TestGetPullRequestByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetPullRequestByID(db.DefaultContext, 1) + pr, err := issues_model.GetPullRequestByID(t.Context(), 1) assert.NoError(t, err) assert.Equal(t, int64(1), pr.ID) assert.Equal(t, int64(2), pr.IssueID) - _, err = issues_model.GetPullRequestByID(db.DefaultContext, 9223372036854775807) + _, err = issues_model.GetPullRequestByID(t.Context(), 9223372036854775807) assert.Error(t, err) assert.True(t, issues_model.IsErrPullRequestNotExist(err)) } func TestGetPullRequestByIssueID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetPullRequestByIssueID(db.DefaultContext, 2) + pr, err := issues_model.GetPullRequestByIssueID(t.Context(), 2) assert.NoError(t, err) assert.Equal(t, int64(2), pr.IssueID) - _, err = issues_model.GetPullRequestByIssueID(db.DefaultContext, 9223372036854775807) + _, err = issues_model.GetPullRequestByIssueID(t.Context(), 9223372036854775807) assert.Error(t, err) assert.True(t, issues_model.IsErrPullRequestNotExist(err)) } @@ -255,7 +255,7 @@ func TestPullRequest_UpdateCols(t *testing.T) { BaseBranch: "baseBranch", HeadBranch: "headBranch", } - assert.NoError(t, pr.UpdateCols(db.DefaultContext, "head_branch")) + assert.NoError(t, pr.UpdateCols(t.Context(), "head_branch")) pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) assert.Equal(t, "master", pr.BaseBranch) @@ -269,50 +269,50 @@ func TestPullRequest_IsWorkInProgress(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - pr.LoadIssue(db.DefaultContext) + pr.LoadIssue(t.Context()) - assert.False(t, pr.IsWorkInProgress(db.DefaultContext)) + assert.False(t, pr.IsWorkInProgress(t.Context())) pr.Issue.Title = "WIP: " + pr.Issue.Title - assert.True(t, pr.IsWorkInProgress(db.DefaultContext)) + assert.True(t, pr.IsWorkInProgress(t.Context())) pr.Issue.Title = "[wip]: " + pr.Issue.Title - assert.True(t, pr.IsWorkInProgress(db.DefaultContext)) + assert.True(t, pr.IsWorkInProgress(t.Context())) } func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - pr.LoadIssue(db.DefaultContext) + pr.LoadIssue(t.Context()) - assert.Empty(t, pr.GetWorkInProgressPrefix(db.DefaultContext)) + assert.Empty(t, pr.GetWorkInProgressPrefix(t.Context())) original := pr.Issue.Title pr.Issue.Title = "WIP: " + original - assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix(db.DefaultContext)) + assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix(t.Context())) pr.Issue.Title = "[wip] " + original - assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix(db.DefaultContext)) + assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix(t.Context())) } func TestDeleteOrphanedObjects(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - countBefore, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) + countBefore, err := db.GetEngine(t.Context()).Count(&issues_model.PullRequest{}) assert.NoError(t, err) - _, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) + _, err = db.GetEngine(t.Context()).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003}) assert.NoError(t, err) - orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") + orphaned, err := db.CountOrphanedObjects(t.Context(), "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) assert.EqualValues(t, 3, orphaned) - err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") + err = db.DeleteOrphanedObjects(t.Context(), "pull_request", "issue", "pull_request.issue_id=issue.id") assert.NoError(t, err) - countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{}) + countAfter, err := db.GetEngine(t.Context()).Count(&issues_model.PullRequest{}) assert.NoError(t, err) assert.Equal(t, countBefore, countAfter) } @@ -345,20 +345,20 @@ func TestGetApprovers(t *testing.T) { // Official reviews are already deduplicated. Allow unofficial reviews // to assert that there are no duplicated approvers. setting.Repository.PullRequest.DefaultMergeMessageOfficialApproversOnly = false - approvers := pr.GetApprovers(db.DefaultContext) + approvers := pr.GetApprovers(t.Context()) expected := "Reviewed-by: User Five \nReviewed-by: Org Six \n" assert.Equal(t, expected, approvers) } func TestGetPullRequestByMergedCommit(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetPullRequestByMergedCommit(db.DefaultContext, 1, "1a8823cd1a9549fde083f992f6b9b87a7ab74fb3") + pr, err := issues_model.GetPullRequestByMergedCommit(t.Context(), 1, "1a8823cd1a9549fde083f992f6b9b87a7ab74fb3") assert.NoError(t, err) assert.EqualValues(t, 1, pr.ID) - _, err = issues_model.GetPullRequestByMergedCommit(db.DefaultContext, 0, "1a8823cd1a9549fde083f992f6b9b87a7ab74fb3") + _, err = issues_model.GetPullRequestByMergedCommit(t.Context(), 0, "1a8823cd1a9549fde083f992f6b9b87a7ab74fb3") assert.ErrorAs(t, err, &issues_model.ErrPullRequestNotExist{}) - _, err = issues_model.GetPullRequestByMergedCommit(db.DefaultContext, 1, "") + _, err = issues_model.GetPullRequestByMergedCommit(t.Context(), 1, "") assert.ErrorAs(t, err, &issues_model.ErrPullRequestNotExist{}) } @@ -382,7 +382,7 @@ func TestMigrate_InsertPullRequests(t *testing.T) { Issue: i, } - err := issues_model.InsertPullRequests(db.DefaultContext, p) + err := issues_model.InsertPullRequests(t.Context(), p) assert.NoError(t, err) _ = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{IssueID: i.ID}) diff --git a/models/issues/review_test.go b/models/issues/review_test.go index 2588b8ba41b..7b8537cc7df 100644 --- a/models/issues/review_test.go +++ b/models/issues/review_test.go @@ -6,7 +6,6 @@ package issues_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -17,12 +16,12 @@ import ( func TestGetReviewByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - review, err := issues_model.GetReviewByID(db.DefaultContext, 1) + review, err := issues_model.GetReviewByID(t.Context(), 1) assert.NoError(t, err) assert.Equal(t, "Demo Review", review.Content) assert.Equal(t, issues_model.ReviewTypeApprove, review.Type) - _, err = issues_model.GetReviewByID(db.DefaultContext, 23892) + _, err = issues_model.GetReviewByID(t.Context(), 23892) assert.Error(t, err) assert.True(t, issues_model.IsErrReviewNotExist(err), "IsErrReviewNotExist") } @@ -30,23 +29,23 @@ func TestGetReviewByID(t *testing.T) { func TestReview_LoadAttributes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 1}) - assert.NoError(t, review.LoadAttributes(db.DefaultContext)) + assert.NoError(t, review.LoadAttributes(t.Context())) assert.NotNil(t, review.Issue) assert.NotNil(t, review.Reviewer) invalidReview1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 2}) - assert.Error(t, invalidReview1.LoadAttributes(db.DefaultContext)) + assert.Error(t, invalidReview1.LoadAttributes(t.Context())) invalidReview2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 3}) - assert.Error(t, invalidReview2.LoadAttributes(db.DefaultContext)) + assert.Error(t, invalidReview2.LoadAttributes(t.Context())) } func TestReview_LoadCodeComments(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 4}) - assert.NoError(t, review.LoadAttributes(db.DefaultContext)) - assert.NoError(t, review.LoadCodeComments(db.DefaultContext)) + assert.NoError(t, review.LoadAttributes(t.Context())) + assert.NoError(t, review.LoadCodeComments(t.Context())) assert.Len(t, review.CodeComments, 1) assert.Equal(t, int64(4), review.CodeComments["README.md"][int64(4)][0].Line) } @@ -62,7 +61,7 @@ func TestReviewType_Icon(t *testing.T) { func TestFindReviews(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - reviews, err := issues_model.FindReviews(db.DefaultContext, issues_model.FindReviewOptions{ + reviews, err := issues_model.FindReviews(t.Context(), issues_model.FindReviewOptions{ Types: []issues_model.ReviewType{issues_model.ReviewTypeApprove}, IssueID: 2, ReviewerID: 1, @@ -74,7 +73,7 @@ func TestFindReviews(t *testing.T) { func TestFindLatestReviews(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - reviews, err := issues_model.FindLatestReviews(db.DefaultContext, issues_model.FindReviewOptions{ + reviews, err := issues_model.FindLatestReviews(t.Context(), issues_model.FindReviewOptions{ Types: []issues_model.ReviewType{issues_model.ReviewTypeApprove}, IssueID: 11, }) @@ -89,14 +88,14 @@ func TestGetCurrentReview(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - review, err := issues_model.GetCurrentReview(db.DefaultContext, user, issue) + review, err := issues_model.GetCurrentReview(t.Context(), user, issue) assert.NoError(t, err) assert.NotNil(t, review) assert.Equal(t, issues_model.ReviewTypePending, review.Type) assert.Equal(t, "Pending Review", review.Content) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 7}) - review2, err := issues_model.GetCurrentReview(db.DefaultContext, user2, issue) + review2, err := issues_model.GetCurrentReview(t.Context(), user2, issue) assert.Error(t, err) assert.True(t, issues_model.IsErrReviewNotExist(err)) assert.Nil(t, review2) @@ -108,7 +107,7 @@ func TestCreateReview(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - review, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{ + review, err := issues_model.CreateReview(t.Context(), issues_model.CreateReviewOptions{ Content: "New Review", Type: issues_model.ReviewTypePending, Issue: issue, @@ -162,11 +161,11 @@ func TestGetReviewersByIssueID(t *testing.T) { }, ) - allReviews, migratedReviews, err := issues_model.GetReviewsByIssueID(db.DefaultContext, issue.ID) + allReviews, migratedReviews, err := issues_model.GetReviewsByIssueID(t.Context(), issue.ID) assert.NoError(t, err) assert.Empty(t, migratedReviews) for _, review := range allReviews { - assert.NoError(t, review.LoadReviewer(db.DefaultContext)) + assert.NoError(t, review.LoadReviewer(t.Context())) } if assert.Len(t, allReviews, 5) { for i, review := range allReviews { @@ -187,46 +186,46 @@ func TestDismissReview(t *testing.T) { assert.False(t, requestReviewExample.Dismissed) assert.False(t, approveReviewExample.Dismissed) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, rejectReviewExample, true)) + assert.NoError(t, issues_model.DismissReview(t.Context(), rejectReviewExample, true)) rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9}) requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11}) assert.True(t, rejectReviewExample.Dismissed) assert.False(t, requestReviewExample.Dismissed) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, true)) + assert.NoError(t, issues_model.DismissReview(t.Context(), requestReviewExample, true)) rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9}) requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11}) assert.True(t, rejectReviewExample.Dismissed) assert.False(t, requestReviewExample.Dismissed) assert.False(t, approveReviewExample.Dismissed) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, true)) + assert.NoError(t, issues_model.DismissReview(t.Context(), requestReviewExample, true)) rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9}) requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11}) assert.True(t, rejectReviewExample.Dismissed) assert.False(t, requestReviewExample.Dismissed) assert.False(t, approveReviewExample.Dismissed) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, false)) + assert.NoError(t, issues_model.DismissReview(t.Context(), requestReviewExample, false)) rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9}) requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11}) assert.True(t, rejectReviewExample.Dismissed) assert.False(t, requestReviewExample.Dismissed) assert.False(t, approveReviewExample.Dismissed) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, false)) + assert.NoError(t, issues_model.DismissReview(t.Context(), requestReviewExample, false)) rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9}) requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11}) assert.True(t, rejectReviewExample.Dismissed) assert.False(t, requestReviewExample.Dismissed) assert.False(t, approveReviewExample.Dismissed) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, rejectReviewExample, false)) + assert.NoError(t, issues_model.DismissReview(t.Context(), rejectReviewExample, false)) assert.False(t, rejectReviewExample.Dismissed) assert.False(t, requestReviewExample.Dismissed) assert.False(t, approveReviewExample.Dismissed) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, approveReviewExample, true)) + assert.NoError(t, issues_model.DismissReview(t.Context(), approveReviewExample, true)) assert.False(t, rejectReviewExample.Dismissed) assert.False(t, requestReviewExample.Dismissed) assert.True(t, approveReviewExample.Dismissed) @@ -238,7 +237,7 @@ func TestDeleteReview(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - review1, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{ + review1, err := issues_model.CreateReview(t.Context(), issues_model.CreateReviewOptions{ Content: "Official rejection", Type: issues_model.ReviewTypeReject, Official: false, @@ -247,7 +246,7 @@ func TestDeleteReview(t *testing.T) { }) assert.NoError(t, err) - review2, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{ + review2, err := issues_model.CreateReview(t.Context(), issues_model.CreateReviewOptions{ Content: "Official approval", Type: issues_model.ReviewTypeApprove, Official: true, @@ -256,13 +255,13 @@ func TestDeleteReview(t *testing.T) { }) assert.NoError(t, err) - assert.NoError(t, issues_model.DeleteReview(db.DefaultContext, review2)) + assert.NoError(t, issues_model.DeleteReview(t.Context(), review2)) - _, err = issues_model.GetReviewByID(db.DefaultContext, review2.ID) + _, err = issues_model.GetReviewByID(t.Context(), review2.ID) assert.Error(t, err) assert.True(t, issues_model.IsErrReviewNotExist(err), "IsErrReviewNotExist") - review1, err = issues_model.GetReviewByID(db.DefaultContext, review1.ID) + review1, err = issues_model.GetReviewByID(t.Context(), review1.ID) assert.NoError(t, err) assert.True(t, review1.Official) } @@ -273,7 +272,7 @@ func TestDeleteDismissedReview(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID}) - review, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{ + review, err := issues_model.CreateReview(t.Context(), issues_model.CreateReviewOptions{ Content: "reject", Type: issues_model.ReviewTypeReject, Official: false, @@ -281,8 +280,8 @@ func TestDeleteDismissedReview(t *testing.T) { Reviewer: user, }) assert.NoError(t, err) - assert.NoError(t, issues_model.DismissReview(db.DefaultContext, review, true)) - comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{ + assert.NoError(t, issues_model.DismissReview(t.Context(), review, true)) + comment, err := issues_model.CreateComment(t.Context(), &issues_model.CreateCommentOptions{ Type: issues_model.CommentTypeDismissReview, Doer: user, Repo: repo, @@ -292,7 +291,7 @@ func TestDeleteDismissedReview(t *testing.T) { }) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: comment.ID}) - assert.NoError(t, issues_model.DeleteReview(db.DefaultContext, review)) + assert.NoError(t, issues_model.DeleteReview(t.Context(), review)) unittest.AssertNotExistsBean(t, &issues_model.Comment{ID: comment.ID}) } @@ -300,11 +299,11 @@ func TestAddReviewRequest(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pull.LoadIssue(db.DefaultContext)) + assert.NoError(t, pull.LoadIssue(t.Context())) issue := pull.Issue - assert.NoError(t, issue.LoadRepo(db.DefaultContext)) + assert.NoError(t, issue.LoadRepo(t.Context())) reviewer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - _, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{ + _, err := issues_model.CreateReview(t.Context(), issues_model.CreateReviewOptions{ Issue: issue, Reviewer: reviewer, Type: issues_model.ReviewTypeReject, @@ -312,16 +311,16 @@ func TestAddReviewRequest(t *testing.T) { assert.NoError(t, err) pull.HasMerged = false - assert.NoError(t, pull.UpdateCols(db.DefaultContext, "has_merged")) + assert.NoError(t, pull.UpdateCols(t.Context(), "has_merged")) issue.IsClosed = true - _, err = issues_model.AddReviewRequest(db.DefaultContext, issue, reviewer, &user_model.User{}) + _, err = issues_model.AddReviewRequest(t.Context(), issue, reviewer, &user_model.User{}) assert.Error(t, err) assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err)) pull.HasMerged = true - assert.NoError(t, pull.UpdateCols(db.DefaultContext, "has_merged")) + assert.NoError(t, pull.UpdateCols(t.Context(), "has_merged")) issue.IsClosed = false - _, err = issues_model.AddReviewRequest(db.DefaultContext, issue, reviewer, &user_model.User{}) + _, err = issues_model.AddReviewRequest(t.Context(), issue, reviewer, &user_model.User{}) assert.Error(t, err) assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err)) } diff --git a/models/issues/stopwatch_test.go b/models/issues/stopwatch_test.go index 6333c10234b..684ec6cd319 100644 --- a/models/issues/stopwatch_test.go +++ b/models/issues/stopwatch_test.go @@ -6,7 +6,6 @@ package issues_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -20,32 +19,32 @@ func TestCancelStopwatch(t *testing.T) { user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) issue1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) - ok, err := issues_model.CancelStopwatch(db.DefaultContext, user1, issue1) + ok, err := issues_model.CancelStopwatch(t.Context(), user1, issue1) assert.NoError(t, err) assert.True(t, ok) unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user1.ID, IssueID: issue1.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeCancelTracking, PosterID: user1.ID, IssueID: issue1.ID}) - ok, err = issues_model.CancelStopwatch(db.DefaultContext, user1, issue1) + ok, err = issues_model.CancelStopwatch(t.Context(), user1, issue1) assert.NoError(t, err) assert.False(t, ok) } func TestStopwatchExists(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.True(t, issues_model.StopwatchExists(db.DefaultContext, 1, 1)) - assert.False(t, issues_model.StopwatchExists(db.DefaultContext, 1, 2)) + assert.True(t, issues_model.StopwatchExists(t.Context(), 1, 1)) + assert.False(t, issues_model.StopwatchExists(t.Context(), 1, 2)) } func TestHasUserStopwatch(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - exists, sw, _, err := issues_model.HasUserStopwatch(db.DefaultContext, 1) + exists, sw, _, err := issues_model.HasUserStopwatch(t.Context(), 1) assert.NoError(t, err) assert.True(t, exists) assert.Equal(t, int64(1), sw.ID) - exists, _, _, err = issues_model.HasUserStopwatch(db.DefaultContext, 3) + exists, _, _, err = issues_model.HasUserStopwatch(t.Context(), 3) assert.NoError(t, err) assert.False(t, exists) } @@ -58,16 +57,16 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) { issue3 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3}) // create a new stopwatch - ok, err := issues_model.CreateIssueStopwatch(db.DefaultContext, user4, issue1) + ok, err := issues_model.CreateIssueStopwatch(t.Context(), user4, issue1) assert.NoError(t, err) assert.True(t, ok) unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: user4.ID, IssueID: issue1.ID}) // should not create a second stopwatch for the same issue - ok, err = issues_model.CreateIssueStopwatch(db.DefaultContext, user4, issue1) + ok, err = issues_model.CreateIssueStopwatch(t.Context(), user4, issue1) assert.NoError(t, err) assert.False(t, ok) // on a different issue, it will finish the existing stopwatch and create a new one - ok, err = issues_model.CreateIssueStopwatch(db.DefaultContext, user4, issue3) + ok, err = issues_model.CreateIssueStopwatch(t.Context(), user4, issue3) assert.NoError(t, err) assert.True(t, ok) unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user4.ID, IssueID: issue1.ID}) @@ -76,12 +75,12 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) { // user2 already has a stopwatch in test fixture user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) - ok, err = issues_model.FinishIssueStopwatch(db.DefaultContext, user2, issue2) + ok, err = issues_model.FinishIssueStopwatch(t.Context(), user2, issue2) assert.NoError(t, err) assert.True(t, ok) unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user2.ID, IssueID: issue2.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{UserID: user2.ID, IssueID: issue2.ID}) - ok, err = issues_model.FinishIssueStopwatch(db.DefaultContext, user2, issue2) + ok, err = issues_model.FinishIssueStopwatch(t.Context(), user2, issue2) assert.NoError(t, err) assert.False(t, ok) } diff --git a/models/issues/tracked_time_test.go b/models/issues/tracked_time_test.go index 44054a1b836..ef7c72958fc 100644 --- a/models/issues/tracked_time_test.go +++ b/models/issues/tracked_time_test.go @@ -7,7 +7,6 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -19,14 +18,14 @@ import ( func TestAddTime(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - org3, err := user_model.GetUserByID(db.DefaultContext, 3) + org3, err := user_model.GetUserByID(t.Context(), 3) assert.NoError(t, err) - issue1, err := issues_model.GetIssueByID(db.DefaultContext, 1) + issue1, err := issues_model.GetIssueByID(t.Context(), 1) assert.NoError(t, err) // 3661 = 1h 1min 1s - trackedTime, err := issues_model.AddTime(db.DefaultContext, org3, issue1, 3661, time.Now()) + trackedTime, err := issues_model.AddTime(t.Context(), org3, issue1, 3661, time.Now()) assert.NoError(t, err) assert.Equal(t, int64(3), trackedTime.UserID) assert.Equal(t, int64(1), trackedTime.IssueID) @@ -43,39 +42,39 @@ func TestGetTrackedTimes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // by Issue - times, err := issues_model.GetTrackedTimes(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 1}) + times, err := issues_model.GetTrackedTimes(t.Context(), &issues_model.FindTrackedTimesOptions{IssueID: 1}) assert.NoError(t, err) assert.Len(t, times, 1) assert.Equal(t, int64(400), times[0].Time) - times, err = issues_model.GetTrackedTimes(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: -1}) + times, err = issues_model.GetTrackedTimes(t.Context(), &issues_model.FindTrackedTimesOptions{IssueID: -1}) assert.NoError(t, err) assert.Empty(t, times) // by User - times, err = issues_model.GetTrackedTimes(db.DefaultContext, &issues_model.FindTrackedTimesOptions{UserID: 1}) + times, err = issues_model.GetTrackedTimes(t.Context(), &issues_model.FindTrackedTimesOptions{UserID: 1}) assert.NoError(t, err) assert.Len(t, times, 3) assert.Equal(t, int64(400), times[0].Time) - times, err = issues_model.GetTrackedTimes(db.DefaultContext, &issues_model.FindTrackedTimesOptions{UserID: 3}) + times, err = issues_model.GetTrackedTimes(t.Context(), &issues_model.FindTrackedTimesOptions{UserID: 3}) assert.NoError(t, err) assert.Empty(t, times) // by Repo - times, err = issues_model.GetTrackedTimes(db.DefaultContext, &issues_model.FindTrackedTimesOptions{RepositoryID: 2}) + times, err = issues_model.GetTrackedTimes(t.Context(), &issues_model.FindTrackedTimesOptions{RepositoryID: 2}) assert.NoError(t, err) assert.Len(t, times, 3) assert.Equal(t, int64(1), times[0].Time) - issue, err := issues_model.GetIssueByID(db.DefaultContext, times[0].IssueID) + issue, err := issues_model.GetIssueByID(t.Context(), times[0].IssueID) assert.NoError(t, err) assert.Equal(t, int64(2), issue.RepoID) - times, err = issues_model.GetTrackedTimes(db.DefaultContext, &issues_model.FindTrackedTimesOptions{RepositoryID: 1}) + times, err = issues_model.GetTrackedTimes(t.Context(), &issues_model.FindTrackedTimesOptions{RepositoryID: 1}) assert.NoError(t, err) assert.Len(t, times, 5) - times, err = issues_model.GetTrackedTimes(db.DefaultContext, &issues_model.FindTrackedTimesOptions{RepositoryID: 10}) + times, err = issues_model.GetTrackedTimes(t.Context(), &issues_model.FindTrackedTimesOptions{RepositoryID: 10}) assert.NoError(t, err) assert.Empty(t, times) } @@ -83,7 +82,7 @@ func TestGetTrackedTimes(t *testing.T) { func TestTotalTimesForEachUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - total, err := issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 1}) + total, err := issues_model.TotalTimesForEachUser(t.Context(), &issues_model.FindTrackedTimesOptions{IssueID: 1}) assert.NoError(t, err) assert.Len(t, total, 1) for user, time := range total { @@ -91,7 +90,7 @@ func TestTotalTimesForEachUser(t *testing.T) { assert.EqualValues(t, 400, time) } - total, err = issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 2}) + total, err = issues_model.TotalTimesForEachUser(t.Context(), &issues_model.FindTrackedTimesOptions{IssueID: 2}) assert.NoError(t, err) assert.Len(t, total, 2) for user, time := range total { @@ -104,7 +103,7 @@ func TestTotalTimesForEachUser(t *testing.T) { } } - total, err = issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 5}) + total, err = issues_model.TotalTimesForEachUser(t.Context(), &issues_model.FindTrackedTimesOptions{IssueID: 5}) assert.NoError(t, err) assert.Len(t, total, 1) for user, time := range total { @@ -112,7 +111,7 @@ func TestTotalTimesForEachUser(t *testing.T) { assert.EqualValues(t, 1, time) } - total, err = issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 4}) + total, err = issues_model.TotalTimesForEachUser(t.Context(), &issues_model.FindTrackedTimesOptions{IssueID: 4}) assert.NoError(t, err) assert.Len(t, total, 2) } @@ -120,15 +119,15 @@ func TestTotalTimesForEachUser(t *testing.T) { func TestGetIssueTotalTrackedTime(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - ttt, err := issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.Some(false)) + ttt, err := issues_model.GetIssueTotalTrackedTime(t.Context(), &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.Some(false)) assert.NoError(t, err) assert.EqualValues(t, 3682, ttt) - ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.Some(true)) + ttt, err = issues_model.GetIssueTotalTrackedTime(t.Context(), &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.Some(true)) assert.NoError(t, err) assert.EqualValues(t, 0, ttt) - ttt, err = issues_model.GetIssueTotalTrackedTime(db.DefaultContext, &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.None[bool]()) + ttt, err = issues_model.GetIssueTotalTrackedTime(t.Context(), &issues_model.IssuesOptions{MilestoneIDs: []int64{1}}, optional.None[bool]()) assert.NoError(t, err) assert.EqualValues(t, 3682, ttt) } diff --git a/models/migrations/base/tests.go b/models/migrations/base/tests.go index 33fd1df707d..3b52a5e7c72 100644 --- a/models/migrations/base/tests.go +++ b/models/migrations/base/tests.go @@ -4,7 +4,6 @@ package base import ( - "context" "fmt" "os" "path/filepath" @@ -124,7 +123,7 @@ func MainTest(m *testing.M) { setting.AppDataPath = tmpDataPath unittest.InitSettingsForTesting() - if err = git.InitFull(context.Background()); err != nil { + if err = git.InitFull(); err != nil { testlogger.Fatalf("Unable to InitFull: %v\n", err) } setting.LoadDBSetting() diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 4f899453b5f..88967a8b870 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -42,17 +42,24 @@ const minDBVersion = 70 // Gitea 1.5.3 type migration struct { idNumber int64 // DB version is "the last migration's idNumber" + 1 description string - migrate func(*xorm.Engine) error + migrate func(context.Context, *xorm.Engine) error } // newMigration creates a new migration -func newMigration(idNumber int64, desc string, fn func(*xorm.Engine) error) *migration { - return &migration{idNumber, desc, fn} +func newMigration[T func(*xorm.Engine) error | func(context.Context, *xorm.Engine) error](idNumber int64, desc string, fn T) *migration { + m := &migration{idNumber: idNumber, description: desc} + var ok bool + if m.migrate, ok = any(fn).(func(context.Context, *xorm.Engine) error); !ok { + m.migrate = func(ctx context.Context, x *xorm.Engine) error { + return any(fn).(func(*xorm.Engine) error)(x) + } + } + return m } // Migrate executes the migration -func (m *migration) Migrate(x *xorm.Engine) error { - return m.migrate(x) +func (m *migration) Migrate(ctx context.Context, x *xorm.Engine) error { + return m.migrate(ctx, x) } // Version describes the version table. Should have only one row with id==1 @@ -456,7 +463,7 @@ func migrationIDNumberToDBVersion(idNumber int64) int64 { } // Migrate database to current version -func Migrate(x *xorm.Engine) error { +func Migrate(ctx context.Context, x *xorm.Engine) error { migrations := prepareMigrationTasks() maxDBVer := calcDBVersion(migrations) @@ -500,10 +507,8 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t } // Some migration tasks depend on the git command - if git.DefaultContext == nil { - if err = git.InitSimple(context.Background()); err != nil { - return err - } + if err = git.InitSimple(); err != nil { + return err } // Migrate @@ -511,7 +516,7 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t log.Info("Migration[%d]: %s", m.idNumber, m.description) // Reset the mapper between each migration - migrations are not supposed to depend on each other x.SetMapper(names.GonicMapper{}) - if err = m.Migrate(x); err != nil { + if err = m.Migrate(ctx, x); err != nil { return fmt.Errorf("migration[%d]: %s failed: %w", m.idNumber, m.description, err) } currentVersion.Version = migrationIDNumberToDBVersion(m.idNumber) diff --git a/models/migrations/v1_12/v128.go b/models/migrations/v1_12/v128.go index e7dbff37660..d2e8b86a3d9 100644 --- a/models/migrations/v1_12/v128.go +++ b/models/migrations/v1_12/v128.go @@ -4,6 +4,7 @@ package v1_12 import ( + "context" "fmt" "math" "path/filepath" @@ -17,7 +18,7 @@ import ( "xorm.io/xorm" ) -func FixMergeBase(x *xorm.Engine) error { +func FixMergeBase(ctx context.Context, x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` OwnerID int64 `xorm:"UNIQUE(s) index"` @@ -82,17 +83,17 @@ func FixMergeBase(x *xorm.Engine) error { if !pr.HasMerged { var err error - pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) if err != nil { var err2 error - pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) if err2 != nil { log.Error("Unable to get merge base for PR ID %d, Index %d in %s/%s. Error: %v & %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err, err2) continue } } } else { - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue @@ -106,7 +107,7 @@ func FixMergeBase(x *xorm.Engine) error { refs = append(refs, gitRefName) cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue diff --git a/models/migrations/v1_12/v134.go b/models/migrations/v1_12/v134.go index 09d743964dc..189d80cc523 100644 --- a/models/migrations/v1_12/v134.go +++ b/models/migrations/v1_12/v134.go @@ -4,6 +4,7 @@ package v1_12 import ( + "context" "fmt" "math" "path/filepath" @@ -17,7 +18,7 @@ import ( "xorm.io/xorm" ) -func RefixMergeBase(x *xorm.Engine) error { +func RefixMergeBase(ctx context.Context, x *xorm.Engine) error { type Repository struct { ID int64 `xorm:"pk autoincr"` OwnerID int64 `xorm:"UNIQUE(s) index"` @@ -79,7 +80,7 @@ func RefixMergeBase(x *xorm.Engine) error { gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index) - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue @@ -94,7 +95,7 @@ func RefixMergeBase(x *xorm.Engine) error { refs = append(refs, gitRefName) cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(git.DefaultContext, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue diff --git a/models/migrations/v1_14/v156.go b/models/migrations/v1_14/v156.go index 2fa5819610e..593d3f9c70c 100644 --- a/models/migrations/v1_14/v156.go +++ b/models/migrations/v1_14/v156.go @@ -4,6 +4,7 @@ package v1_14 import ( + "context" "fmt" "path/filepath" "strings" @@ -24,7 +25,7 @@ func userPath(userName string) string { return filepath.Join(setting.RepoRootPath, strings.ToLower(userName)) } -func FixPublisherIDforTagReleases(x *xorm.Engine) error { +func FixPublisherIDforTagReleases(ctx context.Context, x *xorm.Engine) error { type Release struct { ID int64 RepoID int64 @@ -108,7 +109,7 @@ func FixPublisherIDforTagReleases(x *xorm.Engine) error { return err } } - gitRepo, err = git.OpenRepository(git.DefaultContext, repoPath(repo.OwnerName, repo.Name)) + gitRepo, err = git.OpenRepository(ctx, repoPath(repo.OwnerName, repo.Name)) if err != nil { log.Error("Error whilst opening git repo for [%d]%s/%s. Error: %v", repo.ID, repo.OwnerName, repo.Name, err) return err diff --git a/models/migrations/v1_22/v293_test.go b/models/migrations/v1_22/v293_test.go index 2c8f7683a83..c7b643c7e08 100644 --- a/models/migrations/v1_22/v293_test.go +++ b/models/migrations/v1_22/v293_test.go @@ -6,7 +6,6 @@ package v1_22 import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/project" @@ -32,12 +31,12 @@ func Test_CheckProjectColumnsConsistency(t *testing.T) { assert.True(t, defaultColumn.Default) // check if multiple defaults, previous were removed and last will be kept - expectDefaultColumn, err := project.GetColumn(db.DefaultContext, 2) + expectDefaultColumn, err := project.GetColumn(t.Context(), 2) assert.NoError(t, err) assert.Equal(t, int64(2), expectDefaultColumn.ProjectID) assert.False(t, expectDefaultColumn.Default) - expectNonDefaultColumn, err := project.GetColumn(db.DefaultContext, 3) + expectNonDefaultColumn, err := project.GetColumn(t.Context(), 3) assert.NoError(t, err) assert.Equal(t, int64(2), expectNonDefaultColumn.ProjectID) assert.True(t, expectNonDefaultColumn.Default) diff --git a/models/migrations/v1_9/v82.go b/models/migrations/v1_9/v82.go index c685d3b86b7..f0307bf07aa 100644 --- a/models/migrations/v1_9/v82.go +++ b/models/migrations/v1_9/v82.go @@ -4,6 +4,7 @@ package v1_9 import ( + "context" "fmt" "path/filepath" "strings" @@ -14,7 +15,7 @@ import ( "xorm.io/xorm" ) -func FixReleaseSha1OnReleaseTable(x *xorm.Engine) error { +func FixReleaseSha1OnReleaseTable(ctx context.Context, x *xorm.Engine) error { type Release struct { ID int64 RepoID int64 @@ -98,7 +99,7 @@ func FixReleaseSha1OnReleaseTable(x *xorm.Engine) error { userCache[repo.OwnerID] = user } - gitRepo, err = git.OpenRepository(git.DefaultContext, RepoPath(user.Name, repo.Name)) + gitRepo, err = git.OpenRepository(ctx, RepoPath(user.Name, repo.Name)) if err != nil { return err } diff --git a/models/organization/org.go b/models/organization/org.go index 5eba004d69c..9ece044d6c0 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -159,8 +159,8 @@ func (org *Organization) AvatarLink(ctx context.Context) string { } // HTMLURL returns the organization's full link. -func (org *Organization) HTMLURL() string { - return org.AsUser().HTMLURL() +func (org *Organization) HTMLURL(ctx context.Context) string { + return org.AsUser().HTMLURL(ctx) } // OrganisationLink returns the organization sub page link. diff --git a/models/organization/org_list_test.go b/models/organization/org_list_test.go index a2a25c6f91c..b2a10444225 100644 --- a/models/organization/org_list_test.go +++ b/models/organization/org_list_test.go @@ -25,15 +25,15 @@ func TestOrgList(t *testing.T) { } func testCountOrganizations(t *testing.T) { - expected, err := db.GetEngine(db.DefaultContext).Where("type=?", user_model.UserTypeOrganization).Count(&organization.Organization{}) + expected, err := db.GetEngine(t.Context()).Where("type=?", user_model.UserTypeOrganization).Count(&organization.Organization{}) assert.NoError(t, err) - cnt, err := db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{IncludeVisibility: structs.VisibleTypePrivate}) + cnt, err := db.Count[organization.Organization](t.Context(), organization.FindOrgOptions{IncludeVisibility: structs.VisibleTypePrivate}) assert.NoError(t, err) assert.Equal(t, expected, cnt) } func testFindOrgs(t *testing.T) { - orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err := db.Find[organization.Organization](t.Context(), organization.FindOrgOptions{ UserID: 4, IncludeVisibility: structs.VisibleTypePrivate, }) @@ -42,13 +42,13 @@ func testFindOrgs(t *testing.T) { assert.EqualValues(t, 3, orgs[0].ID) } - orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + orgs, err = db.Find[organization.Organization](t.Context(), organization.FindOrgOptions{ UserID: 4, }) assert.NoError(t, err) assert.Empty(t, orgs) - total, err := db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{ + total, err := db.Count[organization.Organization](t.Context(), organization.FindOrgOptions{ UserID: 4, IncludeVisibility: structs.VisibleTypePrivate, }) @@ -57,7 +57,7 @@ func testFindOrgs(t *testing.T) { } func testGetUserOrgsList(t *testing.T) { - orgs, err := organization.GetUserOrgsList(db.DefaultContext, &user_model.User{ID: 4}) + orgs, err := organization.GetUserOrgsList(t.Context(), &user_model.User{ID: 4}) assert.NoError(t, err) if assert.Len(t, orgs, 1) { assert.EqualValues(t, 3, orgs[0].ID) @@ -67,10 +67,10 @@ func testGetUserOrgsList(t *testing.T) { } func testLoadOrgListTeams(t *testing.T) { - orgs, err := organization.GetUserOrgsList(db.DefaultContext, &user_model.User{ID: 4}) + orgs, err := organization.GetUserOrgsList(t.Context(), &user_model.User{ID: 4}) assert.NoError(t, err) assert.Len(t, orgs, 1) - teamsMap, err := organization.OrgList(orgs).LoadTeams(db.DefaultContext) + teamsMap, err := organization.OrgList(orgs).LoadTeams(t.Context()) assert.NoError(t, err) assert.Len(t, teamsMap, 1) assert.Len(t, teamsMap[3], 5) diff --git a/models/organization/org_test.go b/models/organization/org_test.go index 234325a8cd8..e7c4d2f9f74 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -34,7 +34,7 @@ func TestUser_IsOwnedBy(t *testing.T) { {2, 3, false}, } { org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: testCase.OrgID}) - isOwner, err := org.IsOwnedBy(db.DefaultContext, testCase.UserID) + isOwner, err := org.IsOwnedBy(t.Context(), testCase.UserID) assert.NoError(t, err) assert.Equal(t, testCase.ExpectedOwner, isOwner) } @@ -55,7 +55,7 @@ func TestUser_IsOrgMember(t *testing.T) { {2, 3, false}, } { org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: testCase.OrgID}) - isMember, err := org.IsOrgMember(db.DefaultContext, testCase.UserID) + isMember, err := org.IsOrgMember(t.Context(), testCase.UserID) assert.NoError(t, err) assert.Equal(t, testCase.ExpectedMember, isMember) } @@ -64,35 +64,35 @@ func TestUser_IsOrgMember(t *testing.T) { func TestUser_GetTeam(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - team, err := org.GetTeam(db.DefaultContext, "team1") + team, err := org.GetTeam(t.Context(), "team1") assert.NoError(t, err) assert.Equal(t, org.ID, team.OrgID) assert.Equal(t, "team1", team.LowerName) - _, err = org.GetTeam(db.DefaultContext, "does not exist") + _, err = org.GetTeam(t.Context(), "does not exist") assert.True(t, organization.IsErrTeamNotExist(err)) nonOrg := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 2}) - _, err = nonOrg.GetTeam(db.DefaultContext, "team") + _, err = nonOrg.GetTeam(t.Context(), "team") assert.True(t, organization.IsErrTeamNotExist(err)) } func TestUser_GetOwnerTeam(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - team, err := org.GetOwnerTeam(db.DefaultContext) + team, err := org.GetOwnerTeam(t.Context()) assert.NoError(t, err) assert.Equal(t, org.ID, team.OrgID) nonOrg := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 2}) - _, err = nonOrg.GetOwnerTeam(db.DefaultContext) + _, err = nonOrg.GetOwnerTeam(t.Context()) assert.True(t, organization.IsErrTeamNotExist(err)) } func TestUser_GetTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - teams, err := org.LoadTeams(db.DefaultContext) + teams, err := org.LoadTeams(t.Context()) assert.NoError(t, err) if assert.Len(t, teams, 5) { assert.Equal(t, int64(1), teams[0].ID) @@ -106,7 +106,7 @@ func TestUser_GetTeams(t *testing.T) { func TestUser_GetMembers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - members, _, err := org.GetMembers(db.DefaultContext, &user_model.User{IsAdmin: true}) + members, _, err := org.GetMembers(t.Context(), &user_model.User{IsAdmin: true}) assert.NoError(t, err) if assert.Len(t, members, 3) { assert.Equal(t, int64(2), members[0].ID) @@ -118,22 +118,22 @@ func TestUser_GetMembers(t *testing.T) { func TestGetOrgByName(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - org, err := organization.GetOrgByName(db.DefaultContext, "org3") + org, err := organization.GetOrgByName(t.Context(), "org3") assert.NoError(t, err) assert.EqualValues(t, 3, org.ID) assert.Equal(t, "org3", org.Name) - _, err = organization.GetOrgByName(db.DefaultContext, "user2") // user2 is an individual + _, err = organization.GetOrgByName(t.Context(), "user2") // user2 is an individual assert.True(t, organization.IsErrOrgNotExist(err)) - _, err = organization.GetOrgByName(db.DefaultContext, "") // corner case + _, err = organization.GetOrgByName(t.Context(), "") // corner case assert.True(t, organization.IsErrOrgNotExist(err)) } func TestIsOrganizationOwner(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(orgID, userID int64, expected bool) { - isOwner, err := organization.IsOrganizationOwner(db.DefaultContext, orgID, userID) + isOwner, err := organization.IsOrganizationOwner(t.Context(), orgID, userID) assert.NoError(t, err) assert.Equal(t, expected, isOwner) } @@ -147,7 +147,7 @@ func TestIsOrganizationOwner(t *testing.T) { func TestIsOrganizationMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(orgID, userID int64, expected bool) { - isMember, err := organization.IsOrganizationMember(db.DefaultContext, orgID, userID) + isMember, err := organization.IsOrganizationMember(t.Context(), orgID, userID) assert.NoError(t, err) assert.Equal(t, expected, isMember) } @@ -162,7 +162,7 @@ func TestIsOrganizationMember(t *testing.T) { func TestIsPublicMembership(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(orgID, userID int64, expected bool) { - isMember, err := organization.IsPublicMembership(db.DefaultContext, orgID, userID) + isMember, err := organization.IsPublicMembership(t.Context(), orgID, userID) assert.NoError(t, err) assert.Equal(t, expected, isMember) } @@ -226,11 +226,11 @@ func TestRestrictedUserOrgMembers(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - count, err := organization.CountOrgMembers(db.DefaultContext, tc.opts) + count, err := organization.CountOrgMembers(t.Context(), tc.opts) assert.NoError(t, err) assert.EqualValues(t, len(tc.expectedUIDs), count) - members, err := organization.GetOrgUsersByOrgID(db.DefaultContext, tc.opts) + members, err := organization.GetOrgUsersByOrgID(t.Context(), tc.opts) assert.NoError(t, err) memberUIDs := make([]int64, 0, len(members)) for _, member := range members { @@ -250,7 +250,7 @@ func TestGetOrgUsersByOrgID(t *testing.T) { OrgID: 3, } assert.False(t, opts.PublicOnly()) - orgUsers, err := organization.GetOrgUsersByOrgID(db.DefaultContext, opts) + orgUsers, err := organization.GetOrgUsersByOrgID(t.Context(), opts) assert.NoError(t, err) sort.Slice(orgUsers, func(i, j int) bool { return orgUsers[i].ID < orgUsers[j].ID @@ -274,11 +274,11 @@ func TestGetOrgUsersByOrgID(t *testing.T) { opts = &organization.FindOrgMembersOpts{OrgID: 3} assert.True(t, opts.PublicOnly()) - orgUsers, err = organization.GetOrgUsersByOrgID(db.DefaultContext, opts) + orgUsers, err = organization.GetOrgUsersByOrgID(t.Context(), opts) assert.NoError(t, err) assert.Len(t, orgUsers, 2) - orgUsers, err = organization.GetOrgUsersByOrgID(db.DefaultContext, &organization.FindOrgMembersOpts{ + orgUsers, err = organization.GetOrgUsersByOrgID(t.Context(), &organization.FindOrgMembersOpts{ ListOptions: db.ListOptions{}, OrgID: unittest.NonexistentID, }) @@ -290,7 +290,7 @@ func TestChangeOrgUserStatus(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(orgID, userID int64, public bool) { - assert.NoError(t, organization.ChangeOrgUserStatus(db.DefaultContext, orgID, userID, public)) + assert.NoError(t, organization.ChangeOrgUserStatus(t.Context(), orgID, userID, public)) orgUser := unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{OrgID: orgID, UID: userID}) assert.Equal(t, public, orgUser.IsPublic) } @@ -298,14 +298,14 @@ func TestChangeOrgUserStatus(t *testing.T) { testSuccess(3, 2, false) testSuccess(3, 2, false) testSuccess(3, 4, true) - assert.NoError(t, organization.ChangeOrgUserStatus(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID, true)) + assert.NoError(t, organization.ChangeOrgUserStatus(t.Context(), unittest.NonexistentID, unittest.NonexistentID, true)) } func TestUser_GetUserTeamIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) testSuccess := func(userID int64, expected []int64) { - teamIDs, err := org.GetUserTeamIDs(db.DefaultContext, userID) + teamIDs, err := org.GetUserTeamIDs(t.Context(), userID) assert.NoError(t, err) assert.Equal(t, expected, teamIDs) } @@ -318,9 +318,9 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) testSuccess := func(userID, expectedCount int64) { - env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID) + env, err := repo_model.AccessibleReposEnv(t.Context(), org, userID) assert.NoError(t, err) - count, err := env.CountRepos(db.DefaultContext) + count, err := env.CountRepos(t.Context()) assert.NoError(t, err) assert.Equal(t, expectedCount, count) } @@ -332,9 +332,9 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) testSuccess := func(userID int64, expectedRepoIDs []int64) { - env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID) + env, err := repo_model.AccessibleReposEnv(t.Context(), org, userID) assert.NoError(t, err) - repoIDs, err := env.RepoIDs(db.DefaultContext) + repoIDs, err := env.RepoIDs(t.Context()) assert.NoError(t, err) assert.Equal(t, expectedRepoIDs, repoIDs) } @@ -346,9 +346,9 @@ func TestAccessibleReposEnv_MirrorRepos(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) testSuccess := func(userID int64, expectedRepoIDs []int64) { - env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID) + env, err := repo_model.AccessibleReposEnv(t.Context(), org, userID) assert.NoError(t, err) - repos, err := env.MirrorRepos(db.DefaultContext) + repos, err := env.MirrorRepos(t.Context()) assert.NoError(t, err) expectedRepos := make(repo_model.RepositoryList, len(expectedRepoIDs)) for i, repoID := range expectedRepoIDs { @@ -373,12 +373,12 @@ func TestHasOrgVisibleTypePublic(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) + assert.NoError(t, organization.CreateOrganization(t.Context(), org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: org.Name, Type: user_model.UserTypeOrganization}) - test1 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner) - test2 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), org3) - test3 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), nil) + test1 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), owner) + test2 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), org3) + test3 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), nil) assert.True(t, test1) // owner of org assert.True(t, test2) // user not a part of org assert.True(t, test3) // logged out user @@ -396,12 +396,12 @@ func TestHasOrgVisibleTypeLimited(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) + assert.NoError(t, organization.CreateOrganization(t.Context(), org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: org.Name, Type: user_model.UserTypeOrganization}) - test1 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner) - test2 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), org3) - test3 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), nil) + test1 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), owner) + test2 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), org3) + test3 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), nil) assert.True(t, test1) // owner of org assert.True(t, test2) // user not a part of org assert.False(t, test3) // logged out user @@ -419,12 +419,12 @@ func TestHasOrgVisibleTypePrivate(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) + assert.NoError(t, organization.CreateOrganization(t.Context(), org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: org.Name, Type: user_model.UserTypeOrganization}) - test1 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner) - test2 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), org3) - test3 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), nil) + test1 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), owner) + test2 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), org3) + test3 := organization.HasOrgOrUserVisible(t.Context(), org.AsUser(), nil) assert.True(t, test1) // owner of org assert.False(t, test2) // user not a part of org assert.False(t, test3) // logged out user @@ -433,7 +433,7 @@ func TestHasOrgVisibleTypePrivate(t *testing.T) { func TestGetUsersWhoCanCreateOrgRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - users, err := organization.GetUsersWhoCanCreateOrgRepo(db.DefaultContext, 3) + users, err := organization.GetUsersWhoCanCreateOrgRepo(t.Context(), 3) assert.NoError(t, err) assert.Len(t, users, 2) var ids []int64 @@ -442,7 +442,7 @@ func TestGetUsersWhoCanCreateOrgRepo(t *testing.T) { } assert.ElementsMatch(t, ids, []int64{2, 28}) - users, err = organization.GetUsersWhoCanCreateOrgRepo(db.DefaultContext, 7) + users, err = organization.GetUsersWhoCanCreateOrgRepo(t.Context(), 7) assert.NoError(t, err) assert.Len(t, users, 1) assert.NotNil(t, users[5]) @@ -455,15 +455,15 @@ func TestUser_RemoveOrgRepo(t *testing.T) { // remove a repo that does belong to org unittest.AssertExistsAndLoadBean(t, &organization.TeamRepo{RepoID: repo.ID, OrgID: org.ID}) - assert.NoError(t, organization.RemoveOrgRepo(db.DefaultContext, org.ID, repo.ID)) + assert.NoError(t, organization.RemoveOrgRepo(t.Context(), org.ID, repo.ID)) unittest.AssertNotExistsBean(t, &organization.TeamRepo{RepoID: repo.ID, OrgID: org.ID}) unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo.ID}) // repo should still exist // remove a repo that does not belong to org - assert.NoError(t, organization.RemoveOrgRepo(db.DefaultContext, org.ID, repo.ID)) + assert.NoError(t, organization.RemoveOrgRepo(t.Context(), org.ID, repo.ID)) unittest.AssertNotExistsBean(t, &organization.TeamRepo{RepoID: repo.ID, OrgID: org.ID}) - assert.NoError(t, organization.RemoveOrgRepo(db.DefaultContext, org.ID, unittest.NonexistentID)) + assert.NoError(t, organization.RemoveOrgRepo(t.Context(), org.ID, unittest.NonexistentID)) unittest.CheckConsistencyFor(t, &user_model.User{ID: org.ID}, @@ -482,7 +482,7 @@ func TestCreateOrganization(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: newOrgName, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) + assert.NoError(t, organization.CreateOrganization(t.Context(), org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}) ownerTeam := unittest.AssertExistsAndLoadBean(t, @@ -502,7 +502,7 @@ func TestCreateOrganization2(t *testing.T) { } unittest.AssertNotExistsBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}) - err := organization.CreateOrganization(db.DefaultContext, org, owner) + err := organization.CreateOrganization(t.Context(), org, owner) assert.Error(t, err) assert.True(t, organization.IsErrUserNotAllowedCreateOrg(err)) unittest.AssertNotExistsBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}) @@ -516,7 +516,7 @@ func TestCreateOrganization3(t *testing.T) { owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) org := &organization.Organization{Name: "org3"} // should already exist unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: org.Name}) // sanity check - err := organization.CreateOrganization(db.DefaultContext, org, owner) + err := organization.CreateOrganization(t.Context(), org, owner) assert.Error(t, err) assert.True(t, user_model.IsErrUserAlreadyExist(err)) unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) @@ -527,7 +527,7 @@ func TestCreateOrganization4(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - err := organization.CreateOrganization(db.DefaultContext, &organization.Organization{Name: "assets"}, owner) + err := organization.CreateOrganization(t.Context(), &organization.Organization{Name: "assets"}, owner) assert.Error(t, err) assert.True(t, db.IsErrNameReserved(err)) unittest.CheckConsistencyFor(t, &organization.Organization{}, &organization.Team{}) diff --git a/models/organization/org_user_test.go b/models/organization/org_user_test.go index 689544430d2..d21df4b474c 100644 --- a/models/organization/org_user_test.go +++ b/models/organization/org_user_test.go @@ -7,7 +7,6 @@ import ( "fmt" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -37,9 +36,9 @@ func TestUserIsPublicMember(t *testing.T) { } func testUserIsPublicMember(t *testing.T, uid, orgID int64, expected bool) { - user, err := user_model.GetUserByID(db.DefaultContext, uid) + user, err := user_model.GetUserByID(t.Context(), uid) assert.NoError(t, err) - is, err := organization.IsPublicMembership(db.DefaultContext, orgID, user.ID) + is, err := organization.IsPublicMembership(t.Context(), orgID, user.ID) assert.NoError(t, err) assert.Equal(t, expected, is) } @@ -65,9 +64,9 @@ func TestIsUserOrgOwner(t *testing.T) { } func testIsUserOrgOwner(t *testing.T, uid, orgID int64, expected bool) { - user, err := user_model.GetUserByID(db.DefaultContext, uid) + user, err := user_model.GetUserByID(t.Context(), uid) assert.NoError(t, err) - is, err := organization.IsOrganizationOwner(db.DefaultContext, orgID, user.ID) + is, err := organization.IsOrganizationOwner(t.Context(), orgID, user.ID) assert.NoError(t, err) assert.Equal(t, expected, is) } @@ -92,9 +91,9 @@ func TestUserListIsPublicMember(t *testing.T) { } func testUserListIsPublicMember(t *testing.T, orgID int64, expected map[int64]bool) { - org, err := organization.GetOrgByID(db.DefaultContext, orgID) + org, err := organization.GetOrgByID(t.Context(), orgID) assert.NoError(t, err) - _, membersIsPublic, err := org.GetMembers(db.DefaultContext, &user_model.User{IsAdmin: true}) + _, membersIsPublic, err := org.GetMembers(t.Context(), &user_model.User{IsAdmin: true}) assert.NoError(t, err) assert.Equal(t, expected, membersIsPublic) } @@ -119,11 +118,11 @@ func TestUserListIsUserOrgOwner(t *testing.T) { } func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bool) { - org, err := organization.GetOrgByID(db.DefaultContext, orgID) + org, err := organization.GetOrgByID(t.Context(), orgID) assert.NoError(t, err) - members, _, err := org.GetMembers(db.DefaultContext, &user_model.User{IsAdmin: true}) + members, _, err := org.GetMembers(t.Context(), &user_model.User{IsAdmin: true}) assert.NoError(t, err) - assert.Equal(t, expected, organization.IsUserOrgOwner(db.DefaultContext, members, orgID)) + assert.Equal(t, expected, organization.IsUserOrgOwner(t.Context(), members, orgID)) } func TestAddOrgUser(t *testing.T) { @@ -134,7 +133,7 @@ func TestAddOrgUser(t *testing.T) { if unittest.GetBean(t, &organization.OrgUser{OrgID: orgID, UID: userID}) == nil { expectedNumMembers++ } - assert.NoError(t, organization.AddOrgUser(db.DefaultContext, orgID, userID)) + assert.NoError(t, organization.AddOrgUser(t.Context(), orgID, userID)) ou := &organization.OrgUser{OrgID: orgID, UID: userID} unittest.AssertExistsAndLoadBean(t, ou) assert.Equal(t, isPublic, ou.IsPublic) diff --git a/models/organization/org_worktime.go b/models/organization/org_worktime.go index 7b57182a8a7..3ef3e512adc 100644 --- a/models/organization/org_worktime.go +++ b/models/organization/org_worktime.go @@ -4,6 +4,7 @@ package organization import ( + "context" "sort" "code.gitea.io/gitea/models/db" @@ -16,8 +17,8 @@ type WorktimeSumByRepos struct { SumTime int64 } -func GetWorktimeByRepos(org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByRepos, err error) { - err = db.GetEngine(db.DefaultContext). +func GetWorktimeByRepos(ctx context.Context, org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByRepos, err error) { + err = db.GetEngine(ctx). Select("repository.name AS repo_name, SUM(tracked_time.time) AS sum_time"). Table("tracked_time"). Join("INNER", "issue", "tracked_time.issue_id = issue.id"). @@ -41,8 +42,8 @@ type WorktimeSumByMilestones struct { HideRepoName bool } -func GetWorktimeByMilestones(org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByMilestones, err error) { - err = db.GetEngine(db.DefaultContext). +func GetWorktimeByMilestones(ctx context.Context, org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByMilestones, err error) { + err = db.GetEngine(ctx). Select("repository.name AS repo_name, milestone.name AS milestone_name, milestone.id AS milestone_id, milestone.deadline_unix as milestone_deadline, SUM(tracked_time.time) AS sum_time"). Table("tracked_time"). Join("INNER", "issue", "tracked_time.issue_id = issue.id"). @@ -85,8 +86,8 @@ type WorktimeSumByMembers struct { SumTime int64 } -func GetWorktimeByMembers(org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByMembers, err error) { - err = db.GetEngine(db.DefaultContext). +func GetWorktimeByMembers(ctx context.Context, org *Organization, unitFrom, unixTo int64) (results []WorktimeSumByMembers, err error) { + err = db.GetEngine(ctx). Select("`user`.name AS user_name, SUM(tracked_time.time) AS sum_time"). Table("tracked_time"). Join("INNER", "issue", "tracked_time.issue_id = issue.id"). diff --git a/models/organization/team_invite_test.go b/models/organization/team_invite_test.go index 45db8494e81..e9fabed1db5 100644 --- a/models/organization/team_invite_test.go +++ b/models/organization/team_invite_test.go @@ -6,7 +6,6 @@ package organization_test import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -23,26 +22,26 @@ func TestTeamInvite(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // user 2 already added to team 2, should result in error - _, err := organization.CreateTeamInvite(db.DefaultContext, user2, team, user2.Email) + _, err := organization.CreateTeamInvite(t.Context(), user2, team, user2.Email) assert.Error(t, err) }) t.Run("CreateAndRemove", func(t *testing.T) { user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - invite, err := organization.CreateTeamInvite(db.DefaultContext, user1, team, "org3@example.com") + invite, err := organization.CreateTeamInvite(t.Context(), user1, team, "org3@example.com") assert.NotNil(t, invite) assert.NoError(t, err) // Shouldn't allow duplicate invite - _, err = organization.CreateTeamInvite(db.DefaultContext, user1, team, "org3@example.com") + _, err = organization.CreateTeamInvite(t.Context(), user1, team, "org3@example.com") assert.Error(t, err) // should remove invite - assert.NoError(t, organization.RemoveInviteByID(db.DefaultContext, invite.ID, invite.TeamID)) + assert.NoError(t, organization.RemoveInviteByID(t.Context(), invite.ID, invite.TeamID)) // invite should not exist - _, err = organization.GetInviteByToken(db.DefaultContext, invite.Token) + _, err = organization.GetInviteByToken(t.Context(), invite.Token) assert.Error(t, err) }) } diff --git a/models/organization/team_list_test.go b/models/organization/team_list_test.go index 5526446e221..df73f958986 100644 --- a/models/organization/team_list_test.go +++ b/models/organization/team_list_test.go @@ -6,7 +6,6 @@ package organization_test import ( "testing" - "code.gitea.io/gitea/models/db" org_model "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/unittest" @@ -17,7 +16,7 @@ func Test_GetTeamsByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // 1 owner team, 2 normal team - teams, err := org_model.GetTeamsByIDs(db.DefaultContext, []int64{1, 2}) + teams, err := org_model.GetTeamsByIDs(t.Context(), []int64{1, 2}) assert.NoError(t, err) assert.Len(t, teams, 2) assert.Equal(t, "Owners", teams[1].Name) diff --git a/models/organization/team_repo_test.go b/models/organization/team_repo_test.go index 73a06a93c21..af959f46585 100644 --- a/models/organization/team_repo_test.go +++ b/models/organization/team_repo_test.go @@ -6,7 +6,6 @@ package organization_test import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/repo" @@ -22,7 +21,7 @@ func TestGetTeamsWithAccessToRepoUnit(t *testing.T) { org41 := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 41}) repo61 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 61}) - teams, err := organization.GetTeamsWithAccessToAnyRepoUnit(db.DefaultContext, org41.ID, repo61.ID, perm.AccessModeRead, unit.TypePullRequests) + teams, err := organization.GetTeamsWithAccessToAnyRepoUnit(t.Context(), org41.ID, repo61.ID, perm.AccessModeRead, unit.TypePullRequests) assert.NoError(t, err) if assert.Len(t, teams, 2) { assert.EqualValues(t, 21, teams[0].ID) diff --git a/models/organization/team_test.go b/models/organization/team_test.go index b0bf8425846..fea5e8990ab 100644 --- a/models/organization/team_test.go +++ b/models/organization/team_test.go @@ -28,14 +28,14 @@ func TestTeam_IsMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - assert.True(t, team.IsMember(db.DefaultContext, 2)) - assert.False(t, team.IsMember(db.DefaultContext, 4)) - assert.False(t, team.IsMember(db.DefaultContext, unittest.NonexistentID)) + assert.True(t, team.IsMember(t.Context(), 2)) + assert.False(t, team.IsMember(t.Context(), 4)) + assert.False(t, team.IsMember(t.Context(), unittest.NonexistentID)) team = unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - assert.True(t, team.IsMember(db.DefaultContext, 2)) - assert.True(t, team.IsMember(db.DefaultContext, 4)) - assert.False(t, team.IsMember(db.DefaultContext, unittest.NonexistentID)) + assert.True(t, team.IsMember(t.Context(), 2)) + assert.True(t, team.IsMember(t.Context(), 4)) + assert.False(t, team.IsMember(t.Context(), unittest.NonexistentID)) } func TestTeam_GetRepositories(t *testing.T) { @@ -43,7 +43,7 @@ func TestTeam_GetRepositories(t *testing.T) { test := func(teamID int64) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) - repos, err := repo_model.GetTeamRepositories(db.DefaultContext, &repo_model.SearchTeamRepoOptions{ + repos, err := repo_model.GetTeamRepositories(t.Context(), &repo_model.SearchTeamRepoOptions{ TeamID: team.ID, }) assert.NoError(t, err) @@ -61,7 +61,7 @@ func TestTeam_GetMembers(t *testing.T) { test := func(teamID int64) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) - assert.NoError(t, team.LoadMembers(db.DefaultContext)) + assert.NoError(t, team.LoadMembers(t.Context())) assert.Len(t, team.Members, team.NumMembers) for _, member := range team.Members { unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: member.ID, TeamID: teamID}) @@ -75,7 +75,7 @@ func TestGetTeam(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(orgID int64, name string) { - team, err := organization.GetTeam(db.DefaultContext, orgID, name) + team, err := organization.GetTeam(t.Context(), orgID, name) assert.NoError(t, err) assert.Equal(t, orgID, team.OrgID) assert.Equal(t, name, team.Name) @@ -83,9 +83,9 @@ func TestGetTeam(t *testing.T) { testSuccess(3, "Owners") testSuccess(3, "team1") - _, err := organization.GetTeam(db.DefaultContext, 3, "nonexistent") + _, err := organization.GetTeam(t.Context(), 3, "nonexistent") assert.Error(t, err) - _, err = organization.GetTeam(db.DefaultContext, unittest.NonexistentID, "Owners") + _, err = organization.GetTeam(t.Context(), unittest.NonexistentID, "Owners") assert.Error(t, err) } @@ -93,7 +93,7 @@ func TestGetTeamByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(teamID int64) { - team, err := organization.GetTeamByID(db.DefaultContext, teamID) + team, err := organization.GetTeamByID(t.Context(), teamID) assert.NoError(t, err) assert.Equal(t, teamID, team.ID) } @@ -102,14 +102,14 @@ func TestGetTeamByID(t *testing.T) { testSuccess(3) testSuccess(4) - _, err := organization.GetTeamByID(db.DefaultContext, unittest.NonexistentID) + _, err := organization.GetTeamByID(t.Context(), unittest.NonexistentID) assert.Error(t, err) } func TestIsTeamMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(orgID, teamID, userID int64, expected bool) { - isMember, err := organization.IsTeamMember(db.DefaultContext, orgID, teamID, userID) + isMember, err := organization.IsTeamMember(t.Context(), orgID, teamID, userID) assert.NoError(t, err) assert.Equal(t, expected, isMember) } @@ -130,7 +130,7 @@ func TestGetTeamMembers(t *testing.T) { test := func(teamID int64) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) - members, err := organization.GetTeamMembers(db.DefaultContext, &organization.SearchMembersOptions{ + members, err := organization.GetTeamMembers(t.Context(), &organization.SearchMembersOptions{ TeamID: teamID, }) assert.NoError(t, err) @@ -146,7 +146,7 @@ func TestGetTeamMembers(t *testing.T) { func TestGetUserTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(userID int64) { - teams, _, err := organization.SearchTeam(db.DefaultContext, &organization.SearchTeamOptions{UserID: userID}) + teams, _, err := organization.SearchTeam(t.Context(), &organization.SearchTeamOptions{UserID: userID}) assert.NoError(t, err) for _, team := range teams { unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{TeamID: team.ID, UID: userID}) @@ -160,7 +160,7 @@ func TestGetUserTeams(t *testing.T) { func TestGetUserOrgTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(orgID, userID int64) { - teams, err := organization.GetUserOrgTeams(db.DefaultContext, orgID, userID) + teams, err := organization.GetUserOrgTeams(t.Context(), orgID, userID) assert.NoError(t, err) for _, team := range teams { assert.Equal(t, orgID, team.OrgID) @@ -177,7 +177,7 @@ func TestHasTeamRepo(t *testing.T) { test := func(teamID, repoID int64, expected bool) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) - assert.Equal(t, expected, organization.HasTeamRepo(db.DefaultContext, team.OrgID, teamID, repoID)) + assert.Equal(t, expected, organization.HasTeamRepo(t.Context(), team.OrgID, teamID, repoID)) } test(1, 1, false) test(1, 3, true) @@ -192,7 +192,7 @@ func TestUsersInTeamsCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(teamIDs, userIDs []int64, expected int64) { - count, err := organization.UsersInTeamsCount(db.DefaultContext, teamIDs, userIDs) + count, err := organization.UsersInTeamsCount(t.Context(), teamIDs, userIDs) assert.NoError(t, err) assert.Equal(t, expected, count) } diff --git a/models/packages/descriptor.go b/models/packages/descriptor.go index 2d43dc30466..ea0e0d5e734 100644 --- a/models/packages/descriptor.go +++ b/models/packages/descriptor.go @@ -83,13 +83,13 @@ func (pd *PackageDescriptor) VersionWebLink() string { } // PackageHTMLURL returns the absolute package HTML URL -func (pd *PackageDescriptor) PackageHTMLURL() string { - return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HTMLURL(), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName)) +func (pd *PackageDescriptor) PackageHTMLURL(ctx context.Context) string { + return fmt.Sprintf("%s/-/packages/%s/%s", pd.Owner.HTMLURL(ctx), string(pd.Package.Type), url.PathEscape(pd.Package.LowerName)) } // VersionHTMLURL returns the absolute package version HTML URL -func (pd *PackageDescriptor) VersionHTMLURL() string { - return fmt.Sprintf("%s/%s", pd.PackageHTMLURL(), url.PathEscape(pd.Version.LowerVersion)) +func (pd *PackageDescriptor) VersionHTMLURL(ctx context.Context) string { + return fmt.Sprintf("%s/%s", pd.PackageHTMLURL(ctx), url.PathEscape(pd.Version.LowerVersion)) } // CalculateBlobSize returns the total blobs size in bytes diff --git a/models/packages/package_test.go b/models/packages/package_test.go index 7f03151e774..9c71f2980d1 100644 --- a/models/packages/package_test.go +++ b/models/packages/package_test.go @@ -6,7 +6,6 @@ package packages_test import ( "testing" - "code.gitea.io/gitea/models/db" packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -27,7 +26,7 @@ func TestHasOwnerPackages(t *testing.T) { owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - p, err := packages_model.TryInsertPackage(db.DefaultContext, &packages_model.Package{ + p, err := packages_model.TryInsertPackage(t.Context(), &packages_model.Package{ OwnerID: owner.ID, LowerName: "package", }) @@ -35,11 +34,11 @@ func TestHasOwnerPackages(t *testing.T) { assert.NoError(t, err) // A package without package versions gets automatically cleaned up and should return false - has, err := packages_model.HasOwnerPackages(db.DefaultContext, owner.ID) + has, err := packages_model.HasOwnerPackages(t.Context(), owner.ID) assert.False(t, has) assert.NoError(t, err) - pv, err := packages_model.GetOrInsertVersion(db.DefaultContext, &packages_model.PackageVersion{ + pv, err := packages_model.GetOrInsertVersion(t.Context(), &packages_model.PackageVersion{ PackageID: p.ID, LowerVersion: "internal", IsInternal: true, @@ -48,11 +47,11 @@ func TestHasOwnerPackages(t *testing.T) { assert.NoError(t, err) // A package with an internal package version gets automatically cleaned up and should return false - has, err = packages_model.HasOwnerPackages(db.DefaultContext, owner.ID) + has, err = packages_model.HasOwnerPackages(t.Context(), owner.ID) assert.False(t, has) assert.NoError(t, err) - pv, err = packages_model.GetOrInsertVersion(db.DefaultContext, &packages_model.PackageVersion{ + pv, err = packages_model.GetOrInsertVersion(t.Context(), &packages_model.PackageVersion{ PackageID: p.ID, LowerVersion: "normal", IsInternal: false, @@ -61,7 +60,7 @@ func TestHasOwnerPackages(t *testing.T) { assert.NoError(t, err) // A package with a normal package version should return true - has, err = packages_model.HasOwnerPackages(db.DefaultContext, owner.ID) + has, err = packages_model.HasOwnerPackages(t.Context(), owner.ID) assert.True(t, has) assert.NoError(t, err) } diff --git a/models/perm/access/access_test.go b/models/perm/access/access_test.go index 51d625707c5..f01993ab4e4 100644 --- a/models/perm/access/access_test.go +++ b/models/perm/access/access_test.go @@ -35,34 +35,34 @@ func TestAccessLevel(t *testing.T) { // org. owned private repo repo24 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24}) - level, err := access_model.AccessLevel(db.DefaultContext, user2, repo1) + level, err := access_model.AccessLevel(t.Context(), user2, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeOwner, level) - level, err = access_model.AccessLevel(db.DefaultContext, user2, repo3) + level, err = access_model.AccessLevel(t.Context(), user2, repo3) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeOwner, level) - level, err = access_model.AccessLevel(db.DefaultContext, user5, repo1) + level, err = access_model.AccessLevel(t.Context(), user5, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeRead, level) - level, err = access_model.AccessLevel(db.DefaultContext, user5, repo3) + level, err = access_model.AccessLevel(t.Context(), user5, repo3) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeNone, level) // restricted user has no access to a public repo - level, err = access_model.AccessLevel(db.DefaultContext, user29, repo1) + level, err = access_model.AccessLevel(t.Context(), user29, repo1) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeNone, level) // ... unless he's a collaborator - level, err = access_model.AccessLevel(db.DefaultContext, user29, repo4) + level, err = access_model.AccessLevel(t.Context(), user29, repo4) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeWrite, level) // ... or a team member - level, err = access_model.AccessLevel(db.DefaultContext, user29, repo24) + level, err = access_model.AccessLevel(t.Context(), user29, repo24) assert.NoError(t, err) assert.Equal(t, perm_model.AccessModeRead, level) } @@ -79,17 +79,17 @@ func TestHasAccess(t *testing.T) { repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) assert.True(t, repo2.IsPrivate) - has, err := access_model.HasAnyUnitAccess(db.DefaultContext, user1.ID, repo1) + has, err := access_model.HasAnyUnitAccess(t.Context(), user1.ID, repo1) assert.NoError(t, err) assert.True(t, has) - _, err = access_model.HasAnyUnitAccess(db.DefaultContext, user1.ID, repo2) + _, err = access_model.HasAnyUnitAccess(t.Context(), user1.ID, repo2) assert.NoError(t, err) - _, err = access_model.HasAnyUnitAccess(db.DefaultContext, user2.ID, repo1) + _, err = access_model.HasAnyUnitAccess(t.Context(), user2.ID, repo1) assert.NoError(t, err) - _, err = access_model.HasAnyUnitAccess(db.DefaultContext, user2.ID, repo2) + _, err = access_model.HasAnyUnitAccess(t.Context(), user2.ID, repo2) assert.NoError(t, err) } @@ -97,14 +97,14 @@ func TestRepository_RecalculateAccesses(t *testing.T) { // test with organization repo assert.NoError(t, unittest.PrepareTestDatabase()) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - assert.NoError(t, repo1.LoadOwner(db.DefaultContext)) + assert.NoError(t, repo1.LoadOwner(t.Context())) - _, err := db.GetEngine(db.DefaultContext).Delete(&repo_model.Collaboration{UserID: 2, RepoID: 3}) + _, err := db.GetEngine(t.Context()).Delete(&repo_model.Collaboration{UserID: 2, RepoID: 3}) assert.NoError(t, err) - assert.NoError(t, access_model.RecalculateAccesses(db.DefaultContext, repo1)) + assert.NoError(t, access_model.RecalculateAccesses(t.Context(), repo1)) access := &access_model.Access{UserID: 2, RepoID: 3} - has, err := db.GetEngine(db.DefaultContext).Get(access) + has, err := db.GetEngine(t.Context()).Get(access) assert.NoError(t, err) assert.True(t, has) assert.Equal(t, perm_model.AccessModeOwner, access.Mode) @@ -114,13 +114,13 @@ func TestRepository_RecalculateAccesses2(t *testing.T) { // test with non-organization repo assert.NoError(t, unittest.PrepareTestDatabase()) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) - assert.NoError(t, repo1.LoadOwner(db.DefaultContext)) + assert.NoError(t, repo1.LoadOwner(t.Context())) - _, err := db.GetEngine(db.DefaultContext).Delete(&repo_model.Collaboration{UserID: 4, RepoID: 4}) + _, err := db.GetEngine(t.Context()).Delete(&repo_model.Collaboration{UserID: 4, RepoID: 4}) assert.NoError(t, err) - assert.NoError(t, access_model.RecalculateAccesses(db.DefaultContext, repo1)) + assert.NoError(t, access_model.RecalculateAccesses(t.Context(), repo1)) - has, err := db.GetEngine(db.DefaultContext).Get(&access_model.Access{UserID: 4, RepoID: 4}) + has, err := db.GetEngine(t.Context()).Get(&access_model.Access{UserID: 4, RepoID: 4}) assert.NoError(t, err) assert.False(t, has) } diff --git a/models/project/column_test.go b/models/project/column_test.go index 6a615090a5b..948e012c62d 100644 --- a/models/project/column_test.go +++ b/models/project/column_test.go @@ -7,7 +7,6 @@ import ( "fmt" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" @@ -16,29 +15,29 @@ import ( func TestGetDefaultColumn(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projectWithoutDefault, err := GetProjectByID(db.DefaultContext, 5) + projectWithoutDefault, err := GetProjectByID(t.Context(), 5) assert.NoError(t, err) // check if default column was added - column, err := projectWithoutDefault.MustDefaultColumn(db.DefaultContext) + column, err := projectWithoutDefault.MustDefaultColumn(t.Context()) assert.NoError(t, err) assert.Equal(t, int64(5), column.ProjectID) assert.Equal(t, "Done", column.Title) - projectWithMultipleDefaults, err := GetProjectByID(db.DefaultContext, 6) + projectWithMultipleDefaults, err := GetProjectByID(t.Context(), 6) assert.NoError(t, err) // check if multiple defaults were removed - column, err = projectWithMultipleDefaults.MustDefaultColumn(db.DefaultContext) + column, err = projectWithMultipleDefaults.MustDefaultColumn(t.Context()) assert.NoError(t, err) assert.Equal(t, int64(6), column.ProjectID) assert.Equal(t, int64(9), column.ID) // there are 2 default columns in the test data, use the latest one // set 8 as default column - assert.NoError(t, SetDefaultColumn(db.DefaultContext, column.ProjectID, 8)) + assert.NoError(t, SetDefaultColumn(t.Context(), column.ProjectID, 8)) // then 9 will become a non-default column - column, err = GetColumn(db.DefaultContext, 9) + column, err = GetColumn(t.Context(), 9) assert.NoError(t, err) assert.Equal(t, int64(6), column.ProjectID) assert.False(t, column.Default) @@ -49,25 +48,25 @@ func Test_moveIssuesToAnotherColumn(t *testing.T) { column1 := unittest.AssertExistsAndLoadBean(t, &Column{ID: 1, ProjectID: 1}) - issues, err := column1.GetIssues(db.DefaultContext) + issues, err := column1.GetIssues(t.Context()) assert.NoError(t, err) assert.Len(t, issues, 1) assert.EqualValues(t, 1, issues[0].ID) column2 := unittest.AssertExistsAndLoadBean(t, &Column{ID: 2, ProjectID: 1}) - issues, err = column2.GetIssues(db.DefaultContext) + issues, err = column2.GetIssues(t.Context()) assert.NoError(t, err) assert.Len(t, issues, 1) assert.EqualValues(t, 3, issues[0].ID) - err = column1.moveIssuesToAnotherColumn(db.DefaultContext, column2) + err = column1.moveIssuesToAnotherColumn(t.Context(), column2) assert.NoError(t, err) - issues, err = column1.GetIssues(db.DefaultContext) + issues, err = column1.GetIssues(t.Context()) assert.NoError(t, err) assert.Empty(t, issues) - issues, err = column2.GetIssues(db.DefaultContext) + issues, err = column2.GetIssues(t.Context()) assert.NoError(t, err) assert.Len(t, issues, 2) assert.EqualValues(t, 3, issues[0].ID) @@ -80,21 +79,21 @@ func Test_MoveColumnsOnProject(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) project1 := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) - columns, err := project1.GetColumns(db.DefaultContext) + columns, err := project1.GetColumns(t.Context()) assert.NoError(t, err) assert.Len(t, columns, 3) assert.EqualValues(t, 0, columns[0].Sorting) // even if there is no default sorting, the code should also work assert.EqualValues(t, 0, columns[1].Sorting) assert.EqualValues(t, 0, columns[2].Sorting) - err = MoveColumnsOnProject(db.DefaultContext, project1, map[int64]int64{ + err = MoveColumnsOnProject(t.Context(), project1, map[int64]int64{ 0: columns[1].ID, 1: columns[2].ID, 2: columns[0].ID, }) assert.NoError(t, err) - columnsAfter, err := project1.GetColumns(db.DefaultContext) + columnsAfter, err := project1.GetColumns(t.Context()) assert.NoError(t, err) assert.Len(t, columnsAfter, 3) assert.Equal(t, columns[1].ID, columnsAfter[0].ID) @@ -106,18 +105,18 @@ func Test_NewColumn(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) project1 := unittest.AssertExistsAndLoadBean(t, &Project{ID: 1}) - columns, err := project1.GetColumns(db.DefaultContext) + columns, err := project1.GetColumns(t.Context()) assert.NoError(t, err) assert.Len(t, columns, 3) for i := range maxProjectColumns - 3 { - err := NewColumn(db.DefaultContext, &Column{ + err := NewColumn(t.Context(), &Column{ Title: fmt.Sprintf("column-%d", i+4), ProjectID: project1.ID, }) assert.NoError(t, err) } - err = NewColumn(db.DefaultContext, &Column{ + err = NewColumn(t.Context(), &Column{ Title: "column-21", ProjectID: project1.ID, }) diff --git a/models/project/project_test.go b/models/project/project_test.go index c2e924e8aec..4b24615979b 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -34,13 +34,13 @@ func TestIsProjectTypeValid(t *testing.T) { func TestGetProjects(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - projects, err := db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 1}) + projects, err := db.Find[Project](t.Context(), SearchOptions{RepoID: 1}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures assert.Len(t, projects, 1) - projects, err = db.Find[Project](db.DefaultContext, SearchOptions{RepoID: 3}) + projects, err = db.Find[Project](t.Context(), SearchOptions{RepoID: 3}) assert.NoError(t, err) // 1 value for this repo exists in the fixtures @@ -60,24 +60,24 @@ func TestProject(t *testing.T) { CreatorID: 2, } - assert.NoError(t, NewProject(db.DefaultContext, project)) + assert.NoError(t, NewProject(t.Context(), project)) - _, err := GetProjectByID(db.DefaultContext, project.ID) + _, err := GetProjectByID(t.Context(), project.ID) assert.NoError(t, err) // Update project project.Title = "Updated title" - assert.NoError(t, UpdateProject(db.DefaultContext, project)) + assert.NoError(t, UpdateProject(t.Context(), project)) - projectFromDB, err := GetProjectByID(db.DefaultContext, project.ID) + projectFromDB, err := GetProjectByID(t.Context(), project.ID) assert.NoError(t, err) assert.Equal(t, project.Title, projectFromDB.Title) - assert.NoError(t, ChangeProjectStatus(db.DefaultContext, project, true)) + assert.NoError(t, ChangeProjectStatus(t.Context(), project, true)) // Retrieve from DB afresh to check if it is truly closed - projectFromDB, err = GetProjectByID(db.DefaultContext, project.ID) + projectFromDB, err = GetProjectByID(t.Context(), project.ID) assert.NoError(t, err) assert.True(t, projectFromDB.IsClosed) @@ -109,7 +109,7 @@ func TestProjectsSort(t *testing.T) { } for _, tt := range tests { - projects, count, err := db.FindAndCount[Project](db.DefaultContext, SearchOptions{ + projects, count, err := db.FindAndCount[Project](t.Context(), SearchOptions{ OrderBy: GetSearchOrderByBySortType(tt.sortType), }) assert.NoError(t, err) diff --git a/models/repo/attachment_test.go b/models/repo/attachment_test.go index c059ffd39a9..d41008344d5 100644 --- a/models/repo/attachment_test.go +++ b/models/repo/attachment_test.go @@ -6,7 +6,6 @@ package repo_test import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -16,15 +15,15 @@ import ( func TestIncreaseDownloadCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") + attachment, err := repo_model.GetAttachmentByUUID(t.Context(), "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") assert.NoError(t, err) assert.Equal(t, int64(0), attachment.DownloadCount) // increase download count - err = attachment.IncreaseDownloadCount(db.DefaultContext) + err = attachment.IncreaseDownloadCount(t.Context()) assert.NoError(t, err) - attachment, err = repo_model.GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") + attachment, err = repo_model.GetAttachmentByUUID(t.Context(), "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") assert.NoError(t, err) assert.Equal(t, int64(1), attachment.DownloadCount) } @@ -33,11 +32,11 @@ func TestGetByCommentOrIssueID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // count of attachments from issue ID - attachments, err := repo_model.GetAttachmentsByIssueID(db.DefaultContext, 1) + attachments, err := repo_model.GetAttachmentsByIssueID(t.Context(), 1) assert.NoError(t, err) assert.Len(t, attachments, 1) - attachments, err = repo_model.GetAttachmentsByCommentID(db.DefaultContext, 1) + attachments, err = repo_model.GetAttachmentsByCommentID(t.Context(), 1) assert.NoError(t, err) assert.Len(t, attachments, 2) } @@ -45,18 +44,18 @@ func TestGetByCommentOrIssueID(t *testing.T) { func TestDeleteAttachments(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - count, err := repo_model.DeleteAttachmentsByIssue(db.DefaultContext, 4, false) + count, err := repo_model.DeleteAttachmentsByIssue(t.Context(), 4, false) assert.NoError(t, err) assert.Equal(t, 2, count) - count, err = repo_model.DeleteAttachmentsByComment(db.DefaultContext, 2, false) + count, err = repo_model.DeleteAttachmentsByComment(t.Context(), 2, false) assert.NoError(t, err) assert.Equal(t, 2, count) - err = repo_model.DeleteAttachment(db.DefaultContext, &repo_model.Attachment{ID: 8}, false) + err = repo_model.DeleteAttachment(t.Context(), &repo_model.Attachment{ID: 8}, false) assert.NoError(t, err) - attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18") + attachment, err := repo_model.GetAttachmentByUUID(t.Context(), "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18") assert.Error(t, err) assert.True(t, repo_model.IsErrAttachmentNotExist(err)) assert.Nil(t, attachment) @@ -65,7 +64,7 @@ func TestDeleteAttachments(t *testing.T) { func TestGetAttachmentByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - attach, err := repo_model.GetAttachmentByID(db.DefaultContext, 1) + attach, err := repo_model.GetAttachmentByID(t.Context(), 1) assert.NoError(t, err) assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attach.UUID) } @@ -81,12 +80,12 @@ func TestAttachment_DownloadURL(t *testing.T) { func TestUpdateAttachment(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - attach, err := repo_model.GetAttachmentByID(db.DefaultContext, 1) + attach, err := repo_model.GetAttachmentByID(t.Context(), 1) assert.NoError(t, err) assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attach.UUID) attach.Name = "new_name" - assert.NoError(t, repo_model.UpdateAttachment(db.DefaultContext, attach)) + assert.NoError(t, repo_model.UpdateAttachment(t.Context(), attach)) unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{Name: "new_name"}) } @@ -94,7 +93,7 @@ func TestUpdateAttachment(t *testing.T) { func TestGetAttachmentsByUUIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - attachList, err := repo_model.GetAttachmentsByUUIDs(db.DefaultContext, []string{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17", "not-existing-uuid"}) + attachList, err := repo_model.GetAttachmentsByUUIDs(t.Context(), []string{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17", "not-existing-uuid"}) assert.NoError(t, err) assert.Len(t, attachList, 2) assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attachList[0].UUID) diff --git a/models/repo/avatar_test.go b/models/repo/avatar_test.go index fc1f8baeca5..f683a13e843 100644 --- a/models/repo/avatar_test.go +++ b/models/repo/avatar_test.go @@ -6,7 +6,6 @@ package repo import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" @@ -18,11 +17,11 @@ func TestRepoAvatarLink(t *testing.T) { defer test.MockVariableValue(&setting.AppSubURL, "")() repo := &Repository{ID: 1, Avatar: "avatar.png"} - link := repo.AvatarLink(db.DefaultContext) + link := repo.AvatarLink(t.Context()) assert.Equal(t, "https://localhost/repo-avatars/avatar.png", link) setting.AppURL = "https://localhost/sub-path/" setting.AppSubURL = "/sub-path" - link = repo.AvatarLink(db.DefaultContext) + link = repo.AvatarLink(t.Context()) assert.Equal(t, "https://localhost/sub-path/repo-avatars/avatar.png", link) } diff --git a/models/repo/collaboration_test.go b/models/repo/collaboration_test.go index 7b07dbffdf0..7e06bffb725 100644 --- a/models/repo/collaboration_test.go +++ b/models/repo/collaboration_test.go @@ -19,9 +19,9 @@ func TestRepository_GetCollaborators(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(repoID int64) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) - collaborators, _, err := repo_model.GetCollaborators(db.DefaultContext, &repo_model.FindCollaborationOptions{RepoID: repo.ID}) + collaborators, _, err := repo_model.GetCollaborators(t.Context(), &repo_model.FindCollaborationOptions{RepoID: repo.ID}) assert.NoError(t, err) - expectedLen, err := db.GetEngine(db.DefaultContext).Count(&repo_model.Collaboration{RepoID: repoID}) + expectedLen, err := db.GetEngine(t.Context()).Count(&repo_model.Collaboration{RepoID: repoID}) assert.NoError(t, err) assert.Len(t, collaborators, int(expectedLen)) for _, collaborator := range collaborators { @@ -37,14 +37,14 @@ func TestRepository_GetCollaborators(t *testing.T) { // Test db.ListOptions repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22}) - collaborators1, _, err := repo_model.GetCollaborators(db.DefaultContext, &repo_model.FindCollaborationOptions{ + collaborators1, _, err := repo_model.GetCollaborators(t.Context(), &repo_model.FindCollaborationOptions{ ListOptions: db.ListOptions{PageSize: 1, Page: 1}, RepoID: repo.ID, }) assert.NoError(t, err) assert.Len(t, collaborators1, 1) - collaborators2, _, err := repo_model.GetCollaborators(db.DefaultContext, &repo_model.FindCollaborationOptions{ + collaborators2, _, err := repo_model.GetCollaborators(t.Context(), &repo_model.FindCollaborationOptions{ ListOptions: db.ListOptions{PageSize: 1, Page: 2}, RepoID: repo.ID, }) @@ -59,7 +59,7 @@ func TestRepository_IsCollaborator(t *testing.T) { test := func(repoID, userID int64, expected bool) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) - actual, err := repo_model.IsCollaborator(db.DefaultContext, repo.ID, userID) + actual, err := repo_model.IsCollaborator(t.Context(), repo.ID, userID) assert.NoError(t, err) assert.Equal(t, expected, actual) } @@ -73,7 +73,7 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(t.Context(), repo, 4, perm.AccessModeAdmin)) collaboration := unittest.AssertExistsAndLoadBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}) assert.Equal(t, perm.AccessModeAdmin, collaboration.Mode) @@ -81,12 +81,12 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) { access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: repo.ID}) assert.Equal(t, perm.AccessModeAdmin, access.Mode) - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(t.Context(), repo, 4, perm.AccessModeAdmin)) - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin)) + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(t.Context(), repo, unittest.NonexistentID, perm.AccessModeAdmin)) - // Disvard invalid input. - assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessMode(unittest.NonexistentID))) + // Discard invalid input. + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(t.Context(), repo, 4, perm.AccessMode(-1))) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) } @@ -97,31 +97,31 @@ func TestRepository_IsOwnerMemberCollaborator(t *testing.T) { repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // Organisation owner. - actual, err := repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo1, 2) + actual, err := repo_model.IsOwnerMemberCollaborator(t.Context(), repo1, 2) assert.NoError(t, err) assert.True(t, actual) // Team member. - actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo1, 4) + actual, err = repo_model.IsOwnerMemberCollaborator(t.Context(), repo1, 4) assert.NoError(t, err) assert.True(t, actual) // Normal user. - actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo1, 1) + actual, err = repo_model.IsOwnerMemberCollaborator(t.Context(), repo1, 1) assert.NoError(t, err) assert.False(t, actual) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) // Collaborator. - actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo2, 4) + actual, err = repo_model.IsOwnerMemberCollaborator(t.Context(), repo2, 4) assert.NoError(t, err) assert.True(t, actual) repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) // Repository owner. - actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo3, 2) + actual, err = repo_model.IsOwnerMemberCollaborator(t.Context(), repo3, 2) assert.NoError(t, err) assert.True(t, actual) } @@ -132,14 +132,14 @@ func TestRepo_GetCollaboration(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) // Existing collaboration. - collab, err := repo_model.GetCollaboration(db.DefaultContext, repo.ID, 4) + collab, err := repo_model.GetCollaboration(t.Context(), repo.ID, 4) assert.NoError(t, err) assert.NotNil(t, collab) assert.EqualValues(t, 4, collab.UserID) assert.EqualValues(t, 4, collab.RepoID) // Non-existing collaboration. - collab, err = repo_model.GetCollaboration(db.DefaultContext, repo.ID, 1) + collab, err = repo_model.GetCollaboration(t.Context(), repo.ID, 1) assert.NoError(t, err) assert.Nil(t, collab) } diff --git a/models/repo/fork_test.go b/models/repo/fork_test.go index e8dca204cc4..e33b6f2f0a1 100644 --- a/models/repo/fork_test.go +++ b/models/repo/fork_test.go @@ -6,7 +6,6 @@ package repo_test import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -17,17 +16,17 @@ func TestGetUserFork(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // User13 has repo 11 forked from repo10 - repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 10) + repo, err := repo_model.GetRepositoryByID(t.Context(), 10) assert.NoError(t, err) assert.NotNil(t, repo) - repo, err = repo_model.GetUserFork(db.DefaultContext, repo.ID, 13) + repo, err = repo_model.GetUserFork(t.Context(), repo.ID, 13) assert.NoError(t, err) assert.NotNil(t, repo) - repo, err = repo_model.GetRepositoryByID(db.DefaultContext, 9) + repo, err = repo_model.GetRepositoryByID(t.Context(), 9) assert.NoError(t, err) assert.NotNil(t, repo) - repo, err = repo_model.GetUserFork(db.DefaultContext, repo.ID, 13) + repo, err = repo_model.GetUserFork(t.Context(), repo.ID, 13) assert.NoError(t, err) assert.Nil(t, repo) } diff --git a/models/repo/pushmirror_test.go b/models/repo/pushmirror_test.go index 9fb74711477..777cc5982f6 100644 --- a/models/repo/pushmirror_test.go +++ b/models/repo/pushmirror_test.go @@ -20,26 +20,26 @@ func TestPushMirrorsIterate(t *testing.T) { now := timeutil.TimeStampNow() - db.Insert(db.DefaultContext, &repo_model.PushMirror{ + db.Insert(t.Context(), &repo_model.PushMirror{ RemoteName: "test-1", LastUpdateUnix: now, Interval: 1, }) long, _ := time.ParseDuration("24h") - db.Insert(db.DefaultContext, &repo_model.PushMirror{ + db.Insert(t.Context(), &repo_model.PushMirror{ RemoteName: "test-2", LastUpdateUnix: now, Interval: long, }) - db.Insert(db.DefaultContext, &repo_model.PushMirror{ + db.Insert(t.Context(), &repo_model.PushMirror{ RemoteName: "test-3", LastUpdateUnix: now, Interval: 0, }) - repo_model.PushMirrorsIterate(db.DefaultContext, 1, func(idx int, bean any) error { + repo_model.PushMirrorsIterate(t.Context(), 1, func(idx int, bean any) error { m, ok := bean.(*repo_model.PushMirror) assert.True(t, ok) assert.Equal(t, "test-1", m.RemoteName) diff --git a/models/repo/redirect_test.go b/models/repo/redirect_test.go index 24cf7e89fb6..aa5e5b7c6bc 100644 --- a/models/repo/redirect_test.go +++ b/models/repo/redirect_test.go @@ -6,7 +6,6 @@ package repo_test import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -16,11 +15,11 @@ import ( func TestLookupRedirect(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - repoID, err := repo_model.LookupRedirect(db.DefaultContext, 2, "oldrepo1") + repoID, err := repo_model.LookupRedirect(t.Context(), 2, "oldrepo1") assert.NoError(t, err) assert.EqualValues(t, 1, repoID) - _, err = repo_model.LookupRedirect(db.DefaultContext, unittest.NonexistentID, "doesnotexist") + _, err = repo_model.LookupRedirect(t.Context(), unittest.NonexistentID, "doesnotexist") assert.True(t, repo_model.IsErrRedirectNotExist(err)) } @@ -29,7 +28,7 @@ func TestNewRedirect(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - assert.NoError(t, repo_model.NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "newreponame")) + assert.NoError(t, repo_model.NewRedirect(t.Context(), repo.OwnerID, repo.ID, repo.Name, "newreponame")) unittest.AssertExistsAndLoadBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, @@ -48,7 +47,7 @@ func TestNewRedirect2(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - assert.NoError(t, repo_model.NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "oldrepo1")) + assert.NoError(t, repo_model.NewRedirect(t.Context(), repo.OwnerID, repo.ID, repo.Name, "oldrepo1")) unittest.AssertExistsAndLoadBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, @@ -67,7 +66,7 @@ func TestNewRedirect3(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - assert.NoError(t, repo_model.NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "newreponame")) + assert.NoError(t, repo_model.NewRedirect(t.Context(), repo.OwnerID, repo.ID, repo.Name, "newreponame")) unittest.AssertExistsAndLoadBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, diff --git a/models/repo/release_test.go b/models/repo/release_test.go index 41ea083229d..01f0fb3cff7 100644 --- a/models/repo/release_test.go +++ b/models/repo/release_test.go @@ -6,7 +6,6 @@ package repo import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" @@ -22,14 +21,14 @@ func TestMigrate_InsertReleases(t *testing.T) { Attachments: []*Attachment{a}, } - err := InsertReleases(db.DefaultContext, r) + err := InsertReleases(t.Context(), r) assert.NoError(t, err) } func Test_FindTagsByCommitIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - sha1Rels, err := FindTagsByCommitIDs(db.DefaultContext, 1, "65f1bf27bc3bf70f64657658635e66094edbcb4d") + sha1Rels, err := FindTagsByCommitIDs(t.Context(), 1, "65f1bf27bc3bf70f64657658635e66094edbcb4d") assert.NoError(t, err) assert.Len(t, sha1Rels, 1) rels := sha1Rels["65f1bf27bc3bf70f64657658635e66094edbcb4d"] diff --git a/models/repo/repo.go b/models/repo/repo.go index 2403b3b40ba..73c7e304d2b 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -363,10 +363,8 @@ func (repo *Repository) FullName() string { // HTMLURL returns the repository HTML URL func (repo *Repository) HTMLURL(ctxs ...context.Context) string { - ctx := context.TODO() - if len(ctxs) > 0 { - ctx = ctxs[0] - } + // FIXME: this HTMLURL is still used in mail templates, so the "ctx" is not provided. + ctx := util.OptionalArg(ctxs, context.TODO()) return httplib.MakeAbsoluteURL(ctx, repo.Link()) } diff --git a/models/repo/repo_list_test.go b/models/repo/repo_list_test.go index 7eb76416c20..6cc0d3155ca 100644 --- a/models/repo/repo_list_test.go +++ b/models/repo/repo_list_test.go @@ -184,7 +184,7 @@ func TestSearchRepository(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // test search public repository on explore page - repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{ + repos, count, err := repo_model.SearchRepositoryByName(t.Context(), repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -199,7 +199,7 @@ func TestSearchRepository(t *testing.T) { } assert.Equal(t, int64(1), count) - repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(t.Context(), repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -213,7 +213,7 @@ func TestSearchRepository(t *testing.T) { assert.Len(t, repos, 2) // test search private repository on explore page - repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(t.Context(), repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -229,7 +229,7 @@ func TestSearchRepository(t *testing.T) { } assert.Equal(t, int64(1), count) - repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepositoryByName(t.Context(), repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -244,14 +244,14 @@ func TestSearchRepository(t *testing.T) { assert.Len(t, repos, 3) // Test non existing owner - repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) + repos, count, err = repo_model.SearchRepositoryByName(t.Context(), repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) assert.NoError(t, err) assert.Empty(t, repos) assert.Equal(t, int64(0), count) // Test search within description - repos, count, err = repo_model.SearchRepository(db.DefaultContext, repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(t.Context(), repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -268,7 +268,7 @@ func TestSearchRepository(t *testing.T) { assert.Equal(t, int64(1), count) // Test NOT search within description - repos, count, err = repo_model.SearchRepository(db.DefaultContext, repo_model.SearchRepoOptions{ + repos, count, err = repo_model.SearchRepository(t.Context(), repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10, @@ -286,7 +286,7 @@ func TestSearchRepository(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts) + repos, count, err := repo_model.SearchRepositoryByName(t.Context(), testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) @@ -361,7 +361,7 @@ func TestCountRepository(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - count, err := repo_model.CountRepository(db.DefaultContext, testCase.opts) + count, err := repo_model.CountRepository(t.Context(), testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) @@ -396,7 +396,7 @@ func TestSearchRepositoryByTopicName(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - _, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts) + _, count, err := repo_model.SearchRepositoryByName(t.Context(), testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) }) diff --git a/models/repo/repo_test.go b/models/repo/repo_test.go index 66abe864fc6..ce17789a3ba 100644 --- a/models/repo/repo_test.go +++ b/models/repo/repo_test.go @@ -6,7 +6,6 @@ package repo import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -28,7 +27,7 @@ var ( func TestGetRepositoryCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - ctx := db.DefaultContext + ctx := t.Context() count, err1 := CountRepositories(ctx, countRepospts) privateCount, err2 := CountRepositories(ctx, countReposptsPrivate) publicCount, err3 := CountRepositories(ctx, countReposptsPublic) @@ -42,7 +41,7 @@ func TestGetRepositoryCount(t *testing.T) { func TestGetPublicRepositoryCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - count, err := CountRepositories(db.DefaultContext, countReposptsPublic) + count, err := CountRepositories(t.Context(), countReposptsPublic) assert.NoError(t, err) assert.Equal(t, int64(1), count) } @@ -50,7 +49,7 @@ func TestGetPublicRepositoryCount(t *testing.T) { func TestGetPrivateRepositoryCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - count, err := CountRepositories(db.DefaultContext, countReposptsPrivate) + count, err := CountRepositories(t.Context(), countReposptsPrivate) assert.NoError(t, err) assert.Equal(t, int64(2), count) } @@ -68,11 +67,11 @@ func TestWatchRepo(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 3}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, WatchRepo(db.DefaultContext, user, repo, true)) + assert.NoError(t, WatchRepo(t.Context(), user, repo, true)) unittest.AssertExistsAndLoadBean(t, &Watch{RepoID: repo.ID, UserID: user.ID}) unittest.CheckConsistencyFor(t, &Repository{ID: repo.ID}) - assert.NoError(t, WatchRepo(db.DefaultContext, user, repo, false)) + assert.NoError(t, WatchRepo(t.Context(), user, repo, false)) unittest.AssertNotExistsBean(t, &Watch{RepoID: repo.ID, UserID: user.ID}) unittest.CheckConsistencyFor(t, &Repository{ID: repo.ID}) } @@ -86,7 +85,7 @@ func TestMetas(t *testing.T) { repo.Units = nil - metas := repo.ComposeCommentMetas(db.DefaultContext) + metas := repo.ComposeCommentMetas(t.Context()) assert.Equal(t, "testRepo", metas["repo"]) assert.Equal(t, "testOwner", metas["user"]) @@ -100,7 +99,7 @@ func TestMetas(t *testing.T) { testSuccess := func(expectedStyle string) { repo.Units = []*RepoUnit{&externalTracker} repo.commonRenderingMetas = nil - metas := repo.ComposeCommentMetas(db.DefaultContext) + metas := repo.ComposeCommentMetas(t.Context()) assert.Equal(t, expectedStyle, metas["style"]) assert.Equal(t, "testRepo", metas["repo"]) assert.Equal(t, "testOwner", metas["user"]) @@ -118,10 +117,10 @@ func TestMetas(t *testing.T) { externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markup.IssueNameStyleRegexp testSuccess(markup.IssueNameStyleRegexp) - repo, err := GetRepositoryByID(db.DefaultContext, 3) + repo, err := GetRepositoryByID(t.Context(), 3) assert.NoError(t, err) - metas = repo.ComposeCommentMetas(db.DefaultContext) + metas = repo.ComposeCommentMetas(t.Context()) assert.Contains(t, metas, "org") assert.Contains(t, metas, "teams") assert.Equal(t, "org3", metas["org"]) @@ -132,13 +131,13 @@ func TestGetRepositoryByURL(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) t.Run("InvalidPath", func(t *testing.T) { - repo, err := GetRepositoryByURL(db.DefaultContext, "something") + repo, err := GetRepositoryByURL(t.Context(), "something") assert.Nil(t, repo) assert.Error(t, err) }) testRepo2 := func(t *testing.T, url string) { - repo, err := GetRepositoryByURL(db.DefaultContext, url) + repo, err := GetRepositoryByURL(t.Context(), url) require.NoError(t, err) assert.EqualValues(t, 2, repo.ID) assert.EqualValues(t, 2, repo.OwnerID) @@ -162,7 +161,7 @@ func TestGetRepositoryByURL(t *testing.T) { testRepo2(t, "sshuser@try.gitea.io:user2/repo2.git") testRelax := func(t *testing.T, url string) { - repo, err := GetRepositoryByURLRelax(db.DefaultContext, url) + repo, err := GetRepositoryByURLRelax(t.Context(), url) require.NoError(t, err) assert.Equal(t, int64(2), repo.ID) assert.Equal(t, int64(2), repo.OwnerID) diff --git a/models/repo/star_test.go b/models/repo/star_test.go index b540f54310c..4fd256cd088 100644 --- a/models/repo/star_test.go +++ b/models/repo/star_test.go @@ -21,25 +21,25 @@ func TestStarRepo(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) unittest.AssertNotExistsBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) - assert.NoError(t, repo_model.StarRepo(db.DefaultContext, user, repo, true)) + assert.NoError(t, repo_model.StarRepo(t.Context(), user, repo, true)) unittest.AssertExistsAndLoadBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) - assert.NoError(t, repo_model.StarRepo(db.DefaultContext, user, repo, true)) + assert.NoError(t, repo_model.StarRepo(t.Context(), user, repo, true)) unittest.AssertExistsAndLoadBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) - assert.NoError(t, repo_model.StarRepo(db.DefaultContext, user, repo, false)) + assert.NoError(t, repo_model.StarRepo(t.Context(), user, repo, false)) unittest.AssertNotExistsBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) } func TestIsStaring(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.True(t, repo_model.IsStaring(db.DefaultContext, 2, 4)) - assert.False(t, repo_model.IsStaring(db.DefaultContext, 3, 4)) + assert.True(t, repo_model.IsStaring(t.Context(), 2, 4)) + assert.False(t, repo_model.IsStaring(t.Context(), 3, 4)) } func TestRepository_GetStargazers(t *testing.T) { // repo with stargazers assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) - gazers, err := repo_model.GetStargazers(db.DefaultContext, repo, db.ListOptions{Page: 0}) + gazers, err := repo_model.GetStargazers(t.Context(), repo, db.ListOptions{Page: 0}) assert.NoError(t, err) if assert.Len(t, gazers, 1) { assert.Equal(t, int64(2), gazers[0].ID) @@ -50,7 +50,7 @@ func TestRepository_GetStargazers2(t *testing.T) { // repo with stargazers assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - gazers, err := repo_model.GetStargazers(db.DefaultContext, repo, db.ListOptions{Page: 0}) + gazers, err := repo_model.GetStargazers(t.Context(), repo, db.ListOptions{Page: 0}) assert.NoError(t, err) assert.Empty(t, gazers) } @@ -62,14 +62,14 @@ func TestClearRepoStars(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) unittest.AssertNotExistsBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) - assert.NoError(t, repo_model.StarRepo(db.DefaultContext, user, repo, true)) + assert.NoError(t, repo_model.StarRepo(t.Context(), user, repo, true)) unittest.AssertExistsAndLoadBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) - assert.NoError(t, repo_model.StarRepo(db.DefaultContext, user, repo, false)) + assert.NoError(t, repo_model.StarRepo(t.Context(), user, repo, false)) unittest.AssertNotExistsBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) - assert.NoError(t, repo_model.ClearRepoStars(db.DefaultContext, repo.ID)) + assert.NoError(t, repo_model.ClearRepoStars(t.Context(), repo.ID)) unittest.AssertNotExistsBean(t, &repo_model.Star{UID: user.ID, RepoID: repo.ID}) - gazers, err := repo_model.GetStargazers(db.DefaultContext, repo, db.ListOptions{Page: 0}) + gazers, err := repo_model.GetStargazers(t.Context(), repo, db.ListOptions{Page: 0}) assert.NoError(t, err) assert.Empty(t, gazers) } diff --git a/models/repo/topic_test.go b/models/repo/topic_test.go index b6a7aed7b1d..903b9ad3fac 100644 --- a/models/repo/topic_test.go +++ b/models/repo/topic_test.go @@ -19,47 +19,47 @@ func TestAddTopic(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - topics, err := db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{}) + topics, err := db.Find[repo_model.Topic](t.Context(), &repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) - topics, total, err := db.FindAndCount[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ + topics, total, err := db.FindAndCount[repo_model.Topic](t.Context(), &repo_model.FindTopicOptions{ ListOptions: db.ListOptions{Page: 1, PageSize: 2}, }) assert.NoError(t, err) assert.Len(t, topics, 2) assert.EqualValues(t, 6, total) - topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ + topics, err = db.Find[repo_model.Topic](t.Context(), &repo_model.FindTopicOptions{ RepoID: 1, }) assert.NoError(t, err) assert.Len(t, topics, repo1NrOfTopics) - assert.NoError(t, repo_model.SaveTopics(db.DefaultContext, 2, "golang")) + assert.NoError(t, repo_model.SaveTopics(t.Context(), 2, "golang")) repo2NrOfTopics := 1 - topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{}) + topics, err = db.Find[repo_model.Topic](t.Context(), &repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) - topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ + topics, err = db.Find[repo_model.Topic](t.Context(), &repo_model.FindTopicOptions{ RepoID: 2, }) assert.NoError(t, err) assert.Len(t, topics, repo2NrOfTopics) - assert.NoError(t, repo_model.SaveTopics(db.DefaultContext, 2, "golang", "gitea")) + assert.NoError(t, repo_model.SaveTopics(t.Context(), 2, "golang", "gitea")) repo2NrOfTopics = 2 totalNrOfTopics++ - topic, err := repo_model.GetTopicByName(db.DefaultContext, "gitea") + topic, err := repo_model.GetTopicByName(t.Context(), "gitea") assert.NoError(t, err) assert.Equal(t, 1, topic.RepoCount) - topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{}) + topics, err = db.Find[repo_model.Topic](t.Context(), &repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) - topics, err = db.Find[repo_model.Topic](db.DefaultContext, &repo_model.FindTopicOptions{ + topics, err = db.Find[repo_model.Topic](t.Context(), &repo_model.FindTopicOptions{ RepoID: 2, }) assert.NoError(t, err) diff --git a/models/repo/user_repo_test.go b/models/repo/user_repo_test.go index 50c970344cb..a53cf39dc4c 100644 --- a/models/repo/user_repo_test.go +++ b/models/repo/user_repo_test.go @@ -6,7 +6,6 @@ package repo_test import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -19,21 +18,21 @@ func TestRepoAssignees(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - users, err := repo_model.GetRepoAssignees(db.DefaultContext, repo2) + users, err := repo_model.GetRepoAssignees(t.Context(), repo2) assert.NoError(t, err) assert.Len(t, users, 1) assert.Equal(t, int64(2), users[0].ID) repo21 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 21}) - users, err = repo_model.GetRepoAssignees(db.DefaultContext, repo21) + users, err = repo_model.GetRepoAssignees(t.Context(), repo21) assert.NoError(t, err) if assert.Len(t, users, 4) { assert.ElementsMatch(t, []int64{10, 15, 16, 18}, []int64{users[0].ID, users[1].ID, users[2].ID, users[3].ID}) } // do not return deactivated users - assert.NoError(t, user_model.UpdateUserCols(db.DefaultContext, &user_model.User{ID: 15, IsActive: false}, "is_active")) - users, err = repo_model.GetRepoAssignees(db.DefaultContext, repo21) + assert.NoError(t, user_model.UpdateUserCols(t.Context(), &user_model.User{ID: 15, IsActive: false}, "is_active")) + users, err = repo_model.GetRepoAssignees(t.Context(), repo21) assert.NoError(t, err) if assert.Len(t, users, 3) { assert.NotContains(t, []int64{users[0].ID, users[1].ID, users[2].ID}, 15) @@ -45,12 +44,12 @@ func TestGetIssuePostersWithSearch(t *testing.T) { repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - users, err := repo_model.GetIssuePostersWithSearch(db.DefaultContext, repo2, false, "USER", false /* full name */) + users, err := repo_model.GetIssuePostersWithSearch(t.Context(), repo2, false, "USER", false /* full name */) require.NoError(t, err) require.Len(t, users, 1) assert.Equal(t, "user2", users[0].Name) - users, err = repo_model.GetIssuePostersWithSearch(db.DefaultContext, repo2, false, "TW%O", true /* full name */) + users, err = repo_model.GetIssuePostersWithSearch(t.Context(), repo2, false, "TW%O", true /* full name */) require.NoError(t, err) require.Len(t, users, 1) assert.Equal(t, "user2", users[0].Name) diff --git a/models/repo/watch_test.go b/models/repo/watch_test.go index 7ed72386c94..19e363f6b08 100644 --- a/models/repo/watch_test.go +++ b/models/repo/watch_test.go @@ -18,20 +18,20 @@ import ( func TestIsWatching(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.True(t, repo_model.IsWatching(db.DefaultContext, 1, 1)) - assert.True(t, repo_model.IsWatching(db.DefaultContext, 4, 1)) - assert.True(t, repo_model.IsWatching(db.DefaultContext, 11, 1)) + assert.True(t, repo_model.IsWatching(t.Context(), 1, 1)) + assert.True(t, repo_model.IsWatching(t.Context(), 4, 1)) + assert.True(t, repo_model.IsWatching(t.Context(), 11, 1)) - assert.False(t, repo_model.IsWatching(db.DefaultContext, 1, 5)) - assert.False(t, repo_model.IsWatching(db.DefaultContext, 8, 1)) - assert.False(t, repo_model.IsWatching(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) + assert.False(t, repo_model.IsWatching(t.Context(), 1, 5)) + assert.False(t, repo_model.IsWatching(t.Context(), 8, 1)) + assert.False(t, repo_model.IsWatching(t.Context(), unittest.NonexistentID, unittest.NonexistentID)) } func TestGetWatchers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - watches, err := repo_model.GetWatchers(db.DefaultContext, repo.ID) + watches, err := repo_model.GetWatchers(t.Context(), repo.ID) assert.NoError(t, err) // One watchers are inactive, thus minus 1 assert.Len(t, watches, repo.NumWatches-1) @@ -39,7 +39,7 @@ func TestGetWatchers(t *testing.T) { assert.Equal(t, repo.ID, watch.RepoID) } - watches, err = repo_model.GetWatchers(db.DefaultContext, unittest.NonexistentID) + watches, err = repo_model.GetWatchers(t.Context(), unittest.NonexistentID) assert.NoError(t, err) assert.Empty(t, watches) } @@ -48,7 +48,7 @@ func TestRepository_GetWatchers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - watchers, err := repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + watchers, err := repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, repo.NumWatches) for _, watcher := range watchers { @@ -56,7 +56,7 @@ func TestRepository_GetWatchers(t *testing.T) { } repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 9}) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Empty(t, watchers) } @@ -67,7 +67,7 @@ func TestWatchIfAuto(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) user12 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 12}) - watchers, err := repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + watchers, err := repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, repo.NumWatches) @@ -76,46 +76,46 @@ func TestWatchIfAuto(t *testing.T) { prevCount := repo.NumWatches // Must not add watch - assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 8, 1, true)) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 8, 1, true)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Should not add watch - assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 10, 1, true)) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 10, 1, true)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) setting.Service.AutoWatchOnChanges = true // Must not add watch - assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 8, 1, true)) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 8, 1, true)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Should not add watch - assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 12, 1, false)) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 12, 1, false)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Should add watch - assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 12, 1, true)) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 12, 1, true)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount+1) // Should remove watch, inhibit from adding auto - assert.NoError(t, repo_model.WatchRepo(db.DefaultContext, user12, repo, false)) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, repo_model.WatchRepo(t.Context(), user12, repo, false)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Must not add watch - assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 12, 1, true)) - watchers, err = repo_model.GetRepoWatchers(db.DefaultContext, repo.ID, db.ListOptions{Page: 1}) + assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 12, 1, true)) + watchers, err = repo_model.GetRepoWatchers(t.Context(), repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) } diff --git a/models/repo_test.go b/models/repo_test.go index b6c53fd1976..5273b9d8384 100644 --- a/models/repo_test.go +++ b/models/repo_test.go @@ -6,7 +6,6 @@ package models import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" @@ -15,13 +14,13 @@ import ( func TestCheckRepoStats(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.NoError(t, CheckRepoStats(db.DefaultContext)) + assert.NoError(t, CheckRepoStats(t.Context())) } func TestDoctorUserStarNum(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.NoError(t, DoctorUserStarNum(db.DefaultContext)) + assert.NoError(t, DoctorUserStarNum(t.Context())) } func Test_repoStatsCorrectIssueNumComments(t *testing.T) { @@ -31,7 +30,7 @@ func Test_repoStatsCorrectIssueNumComments(t *testing.T) { assert.NotNil(t, issue2) assert.Equal(t, 0, issue2.NumComments) // the fixture data is wrong, but we don't fix it here - assert.NoError(t, repoStatsCorrectIssueNumComments(db.DefaultContext, 2)) + assert.NoError(t, repoStatsCorrectIssueNumComments(t.Context(), 2)) // reload the issue issue2 = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) assert.Equal(t, 1, issue2.NumComments) diff --git a/models/system/notice.go b/models/system/notice.go index 91bf4be0f6c..f39188f8fb3 100644 --- a/models/system/notice.go +++ b/models/system/notice.go @@ -9,6 +9,7 @@ import ( "time" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/timeutil" @@ -56,8 +57,7 @@ func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...any) // CreateRepositoryNotice creates new system notice with type NoticeRepository. func CreateRepositoryNotice(desc string, args ...any) error { - // Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled - return CreateNotice(db.DefaultContext, NoticeRepository, desc, args...) + return CreateNotice(graceful.GetManager().ShutdownContext(), NoticeRepository, desc, args...) } // RemoveAllWithNotice removes all directories in given path and @@ -66,8 +66,7 @@ func RemoveAllWithNotice(ctx context.Context, title, path string) { if err := util.RemoveAll(path); err != nil { desc := fmt.Sprintf("%s [%s]: %v", title, path, err) log.Warn(title+" [%s]: %v", path, err) - // Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled - if err = CreateNotice(db.DefaultContext, NoticeRepository, desc); err != nil { + if err = CreateNotice(graceful.GetManager().ShutdownContext(), NoticeRepository, desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } } @@ -80,8 +79,7 @@ func RemoveStorageWithNotice(ctx context.Context, bucket storage.ObjectStorage, desc := fmt.Sprintf("%s [%s]: %v", title, path, err) log.Warn(title+" [%s]: %v", path, err) - // Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled - if err = CreateNotice(db.DefaultContext, NoticeRepository, desc); err != nil { + if err = CreateNotice(graceful.GetManager().ShutdownContext(), NoticeRepository, desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } } diff --git a/models/system/notice_test.go b/models/system/notice_test.go index 9fc9e6cce19..802bcf41b1d 100644 --- a/models/system/notice_test.go +++ b/models/system/notice_test.go @@ -29,7 +29,7 @@ func TestCreateNotice(t *testing.T) { Description: "test description", } unittest.AssertNotExistsBean(t, noticeBean) - assert.NoError(t, system.CreateNotice(db.DefaultContext, noticeBean.Type, noticeBean.Description)) + assert.NoError(t, system.CreateNotice(t.Context(), noticeBean.Type, noticeBean.Description)) unittest.AssertExistsAndLoadBean(t, noticeBean) } @@ -47,20 +47,20 @@ func TestCreateRepositoryNotice(t *testing.T) { func TestCountNotices(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.Equal(t, int64(3), system.CountNotices(db.DefaultContext)) + assert.Equal(t, int64(3), system.CountNotices(t.Context())) } func TestNotices(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - notices, err := system.Notices(db.DefaultContext, 1, 2) + notices, err := system.Notices(t.Context(), 1, 2) assert.NoError(t, err) if assert.Len(t, notices, 2) { assert.Equal(t, int64(3), notices[0].ID) assert.Equal(t, int64(2), notices[1].ID) } - notices, err = system.Notices(db.DefaultContext, 2, 2) + notices, err = system.Notices(t.Context(), 2, 2) assert.NoError(t, err) if assert.Len(t, notices, 1) { assert.Equal(t, int64(1), notices[0].ID) @@ -74,7 +74,7 @@ func TestDeleteNotices(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) - assert.NoError(t, system.DeleteNotices(db.DefaultContext, 1, 2)) + assert.NoError(t, system.DeleteNotices(t.Context(), 1, 2)) unittest.AssertNotExistsBean(t, &system.Notice{ID: 1}) unittest.AssertNotExistsBean(t, &system.Notice{ID: 2}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) @@ -87,7 +87,7 @@ func TestDeleteNotices2(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) - assert.NoError(t, system.DeleteNotices(db.DefaultContext, 3, 2)) + assert.NoError(t, system.DeleteNotices(t.Context(), 3, 2)) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) @@ -99,7 +99,7 @@ func TestDeleteNoticesByIDs(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 1}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 3}) - err := db.DeleteByIDs[system.Notice](db.DefaultContext, 1, 3) + err := db.DeleteByIDs[system.Notice](t.Context(), 1, 3) assert.NoError(t, err) unittest.AssertNotExistsBean(t, &system.Notice{ID: 1}) unittest.AssertExistsAndLoadBean(t, &system.Notice{ID: 2}) diff --git a/models/system/setting_test.go b/models/system/setting_test.go index 7e7e0c8fcaa..780a323fe14 100644 --- a/models/system/setting_test.go +++ b/models/system/setting_test.go @@ -17,34 +17,34 @@ func TestSettings(t *testing.T) { keyName := "test.key" assert.NoError(t, unittest.PrepareTestDatabase()) - assert.NoError(t, db.TruncateBeans(db.DefaultContext, &system.Setting{})) + assert.NoError(t, db.TruncateBeans(t.Context(), &system.Setting{})) - rev, settings, err := system.GetAllSettings(db.DefaultContext) + rev, settings, err := system.GetAllSettings(t.Context()) assert.NoError(t, err) assert.Equal(t, 1, rev) assert.Len(t, settings, 1) // there is only one "revision" key - err = system.SetSettings(db.DefaultContext, map[string]string{keyName: "true"}) + err = system.SetSettings(t.Context(), map[string]string{keyName: "true"}) assert.NoError(t, err) - rev, settings, err = system.GetAllSettings(db.DefaultContext) + rev, settings, err = system.GetAllSettings(t.Context()) assert.NoError(t, err) assert.Equal(t, 2, rev) assert.Len(t, settings, 2) assert.Equal(t, "true", settings[keyName]) - err = system.SetSettings(db.DefaultContext, map[string]string{keyName: "false"}) + err = system.SetSettings(t.Context(), map[string]string{keyName: "false"}) assert.NoError(t, err) - rev, settings, err = system.GetAllSettings(db.DefaultContext) + rev, settings, err = system.GetAllSettings(t.Context()) assert.NoError(t, err) assert.Equal(t, 3, rev) assert.Len(t, settings, 2) assert.Equal(t, "false", settings[keyName]) // setting the same value should not trigger DuplicateKey error, and the "version" should be increased - err = system.SetSettings(db.DefaultContext, map[string]string{keyName: "false"}) + err = system.SetSettings(t.Context(), map[string]string{keyName: "false"}) assert.NoError(t, err) - rev, settings, err = system.GetAllSettings(db.DefaultContext) + rev, settings, err = system.GetAllSettings(t.Context()) assert.NoError(t, err) assert.Len(t, settings, 2) assert.Equal(t, 4, rev) diff --git a/models/unittest/consistency.go b/models/unittest/consistency.go index 364afb5c528..b51cadce0aa 100644 --- a/models/unittest/consistency.go +++ b/models/unittest/consistency.go @@ -4,6 +4,7 @@ package unittest import ( + "context" "reflect" "strconv" "strings" @@ -22,10 +23,10 @@ const ( modelsCommentTypeComment = 0 ) -var consistencyCheckMap = make(map[string]func(t assert.TestingT, bean any)) +var consistencyCheckMap = make(map[string]func(t TestingT, bean any)) // CheckConsistencyFor test that all matching database entries are consistent -func CheckConsistencyFor(t require.TestingT, beansToCheck ...any) { +func CheckConsistencyFor(t TestingT, beansToCheck ...any) { for _, bean := range beansToCheck { sliceType := reflect.SliceOf(reflect.TypeOf(bean)) sliceValue := reflect.MakeSlice(sliceType, 0, 10) @@ -33,7 +34,7 @@ func CheckConsistencyFor(t require.TestingT, beansToCheck ...any) { ptrToSliceValue := reflect.New(sliceType) ptrToSliceValue.Elem().Set(sliceValue) - assert.NoError(t, db.GetEngine(db.DefaultContext).Table(bean).Find(ptrToSliceValue.Interface())) + assert.NoError(t, db.GetEngine(context.TODO()).Table(bean).Find(ptrToSliceValue.Interface())) sliceValue = ptrToSliceValue.Elem() for i := 0; i < sliceValue.Len(); i++ { @@ -43,7 +44,7 @@ func CheckConsistencyFor(t require.TestingT, beansToCheck ...any) { } } -func checkForConsistency(t require.TestingT, bean any) { +func checkForConsistency(t TestingT, bean any) { tb, err := db.TableInfo(bean) assert.NoError(t, err) f := consistencyCheckMap[tb.Name] @@ -61,7 +62,7 @@ func init() { return i } - checkForUserConsistency := func(t assert.TestingT, bean any) { + checkForUserConsistency := func(t TestingT, bean any) { user := reflectionWrap(bean) AssertCountByCond(t, "repository", builder.Eq{"owner_id": user.int("ID")}, user.int("NumRepos")) AssertCountByCond(t, "star", builder.Eq{"uid": user.int("ID")}, user.int("NumStars")) @@ -75,7 +76,7 @@ func init() { } } - checkForRepoConsistency := func(t assert.TestingT, bean any) { + checkForRepoConsistency := func(t TestingT, bean any) { repo := reflectionWrap(bean) assert.Equal(t, repo.str("LowerName"), strings.ToLower(repo.str("Name")), "repo: %+v", repo) AssertCountByCond(t, "star", builder.Eq{"repo_id": repo.int("ID")}, repo.int("NumStars")) @@ -111,7 +112,7 @@ func init() { "Unexpected number of closed milestones for repo id: %d", repo.int("ID")) } - checkForIssueConsistency := func(t assert.TestingT, bean any) { + checkForIssueConsistency := func(t TestingT, bean any) { issue := reflectionWrap(bean) typeComment := modelsCommentTypeComment actual := GetCountByCond(t, "comment", builder.Eq{"`type`": typeComment, "issue_id": issue.int("ID")}) @@ -122,14 +123,14 @@ func init() { } } - checkForPullRequestConsistency := func(t assert.TestingT, bean any) { + checkForPullRequestConsistency := func(t TestingT, bean any) { pr := reflectionWrap(bean) issueRow := AssertExistsAndLoadMap(t, "issue", builder.Eq{"id": pr.int("IssueID")}) assert.True(t, parseBool(issueRow["is_pull"])) assert.Equal(t, parseInt(issueRow["index"]), pr.int("Index"), "Unexpected index for pull request id: %d", pr.int("ID")) } - checkForMilestoneConsistency := func(t assert.TestingT, bean any) { + checkForMilestoneConsistency := func(t TestingT, bean any) { milestone := reflectionWrap(bean) AssertCountByCond(t, "issue", builder.Eq{"milestone_id": milestone.int("ID")}, milestone.int("NumIssues")) @@ -143,9 +144,9 @@ func init() { assert.Equal(t, completeness, milestone.int("Completeness")) } - checkForLabelConsistency := func(t assert.TestingT, bean any) { + checkForLabelConsistency := func(t TestingT, bean any) { label := reflectionWrap(bean) - issueLabels, err := db.GetEngine(db.DefaultContext).Table("issue_label"). + issueLabels, err := db.GetEngine(context.TODO()).Table("issue_label"). Where(builder.Eq{"label_id": label.int("ID")}). Query() assert.NoError(t, err) @@ -164,13 +165,13 @@ func init() { assert.EqualValues(t, expected, label.int("NumClosedIssues"), "Unexpected number of closed issues for label id: %d", label.int("ID")) } - checkForTeamConsistency := func(t assert.TestingT, bean any) { + checkForTeamConsistency := func(t TestingT, bean any) { team := reflectionWrap(bean) AssertCountByCond(t, "team_user", builder.Eq{"team_id": team.int("ID")}, team.int("NumMembers")) AssertCountByCond(t, "team_repo", builder.Eq{"team_id": team.int("ID")}, team.int("NumRepos")) } - checkForActionConsistency := func(t assert.TestingT, bean any) { + checkForActionConsistency := func(t TestingT, bean any) { action := reflectionWrap(bean) if action.int("RepoID") != 1700 { // dangling intentional repoRow := AssertExistsAndLoadMap(t, "repository", builder.Eq{"id": action.int("RepoID")}) diff --git a/models/unittest/fixtures.go b/models/unittest/fixtures.go index fb2d2d0085c..a9a01a32275 100644 --- a/models/unittest/fixtures.go +++ b/models/unittest/fixtures.go @@ -23,7 +23,7 @@ var fixturesLoader FixturesLoader // GetXORMEngine gets the XORM engine func GetXORMEngine() (x *xorm.Engine) { - return db.GetEngine(db.DefaultContext).(*xorm.Engine) + return db.GetXORMEngineForTesting() } func loadFixtureResetSeqPgsql(e *xorm.Engine) error { diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index cb60cf5f854..4611a079ec3 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -141,7 +141,7 @@ func MainTest(m *testing.M, testOptsArg ...*TestOptions) { fatalTestError("util.SyncDirs: %v\n", err) } - if err = git.InitFull(context.Background()); err != nil { + if err = git.InitFull(); err != nil { fatalTestError("git.Init: %v\n", err) } diff --git a/models/unittest/unit_tests.go b/models/unittest/unit_tests.go index 4a4cec40aee..49d42d7fe60 100644 --- a/models/unittest/unit_tests.go +++ b/models/unittest/unit_tests.go @@ -4,6 +4,7 @@ package unittest import ( + "context" "fmt" "math" "os" @@ -14,7 +15,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "xorm.io/builder" - "xorm.io/xorm" ) // Code in this file is mainly used by unittest.CheckConsistencyFor, which is not in the unit test for various reasons. @@ -23,6 +23,12 @@ import ( // NonexistentID an ID that will never exist const NonexistentID = int64(math.MaxInt64) +type TestingT interface { + require.TestingT + assert.TestingT + Context() context.Context +} + type testCond struct { query any args []any @@ -55,13 +61,13 @@ func whereOrderConditions(e db.Engine, conditions []any) db.Engine { return e.OrderBy(orderBy) } -func getBeanIfExists(bean any, conditions ...any) (bool, error) { - e := db.GetEngine(db.DefaultContext) +func getBeanIfExists(t TestingT, bean any, conditions ...any) (bool, error) { + e := db.GetEngine(t.Context()) return whereOrderConditions(e, conditions).Get(bean) } -func GetBean[T any](t require.TestingT, bean T, conditions ...any) (ret T) { - exists, err := getBeanIfExists(bean, conditions...) +func GetBean[T any](t TestingT, bean T, conditions ...any) (ret T) { + exists, err := getBeanIfExists(t, bean, conditions...) require.NoError(t, err) if exists { return bean @@ -70,8 +76,8 @@ func GetBean[T any](t require.TestingT, bean T, conditions ...any) (ret T) { } // AssertExistsAndLoadBean assert that a bean exists and load it from the test database -func AssertExistsAndLoadBean[T any](t require.TestingT, bean T, conditions ...any) T { - exists, err := getBeanIfExists(bean, conditions...) +func AssertExistsAndLoadBean[T any](t TestingT, bean T, conditions ...any) T { + exists, err := getBeanIfExists(t, bean, conditions...) require.NoError(t, err) require.True(t, exists, "Expected to find %+v (of type %T, with conditions %+v), but did not", @@ -80,8 +86,8 @@ func AssertExistsAndLoadBean[T any](t require.TestingT, bean T, conditions ...an } // AssertExistsAndLoadMap assert that a row exists and load it from the test database -func AssertExistsAndLoadMap(t assert.TestingT, table string, conditions ...any) map[string]string { - e := db.GetEngine(db.DefaultContext).Table(table) +func AssertExistsAndLoadMap(t TestingT, table string, conditions ...any) map[string]string { + e := db.GetEngine(t.Context()).Table(table) res, err := whereOrderConditions(e, conditions).Query() assert.NoError(t, err) assert.Len(t, res, 1, @@ -100,8 +106,8 @@ func AssertExistsAndLoadMap(t assert.TestingT, table string, conditions ...any) } // GetCount get the count of a bean -func GetCount(t assert.TestingT, bean any, conditions ...any) int { - e := db.GetEngine(db.DefaultContext) +func GetCount(t TestingT, bean any, conditions ...any) int { + e := db.GetEngine(t.Context()) for _, condition := range conditions { switch cond := condition.(type) { case *testCond: @@ -116,14 +122,14 @@ func GetCount(t assert.TestingT, bean any, conditions ...any) int { } // AssertNotExistsBean assert that a bean does not exist in the test database -func AssertNotExistsBean(t assert.TestingT, bean any, conditions ...any) { - exists, err := getBeanIfExists(bean, conditions...) +func AssertNotExistsBean(t TestingT, bean any, conditions ...any) { + exists, err := getBeanIfExists(t, bean, conditions...) assert.NoError(t, err) assert.False(t, exists) } // AssertCount assert the count of a bean -func AssertCount(t assert.TestingT, bean, expected any) bool { +func AssertCount(t TestingT, bean, expected any) bool { return assert.EqualValues(t, expected, GetCount(t, bean)) } @@ -134,22 +140,22 @@ func AssertInt64InRange(t assert.TestingT, low, high, value int64) { } // GetCountByCond get the count of database entries matching bean -func GetCountByCond(t assert.TestingT, tableName string, cond builder.Cond) int64 { - e := db.GetEngine(db.DefaultContext) +func GetCountByCond(t TestingT, tableName string, cond builder.Cond) int64 { + e := db.GetEngine(t.Context()) count, err := e.Table(tableName).Where(cond).Count() assert.NoError(t, err) return count } // AssertCountByCond test the count of database entries matching bean -func AssertCountByCond(t assert.TestingT, tableName string, cond builder.Cond, expected int) bool { +func AssertCountByCond(t TestingT, tableName string, cond builder.Cond, expected int) bool { return assert.EqualValues(t, expected, GetCountByCond(t, tableName, cond), "Failed consistency test, the counted bean (of table %s) was %+v", tableName, cond) } // DumpQueryResult dumps the result of a query for debugging purpose func DumpQueryResult(t require.TestingT, sqlOrBean any, sqlArgs ...any) { - x := db.GetEngine(db.DefaultContext).(*xorm.Engine) + x := GetXORMEngine() goDB := x.DB().DB sql, ok := sqlOrBean.(string) if !ok { diff --git a/models/user/avatar_test.go b/models/user/avatar_test.go index 941068957c2..9ebf00de491 100644 --- a/models/user/avatar_test.go +++ b/models/user/avatar_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" @@ -23,12 +22,12 @@ func TestUserAvatarLink(t *testing.T) { defer test.MockVariableValue(&setting.AppSubURL, "")() u := &User{ID: 1, Avatar: "avatar.png"} - link := u.AvatarLink(db.DefaultContext) + link := u.AvatarLink(t.Context()) assert.Equal(t, "https://localhost/avatars/avatar.png", link) setting.AppURL = "https://localhost/sub-path/" setting.AppSubURL = "/sub-path" - link = u.AvatarLink(db.DefaultContext) + link = u.AvatarLink(t.Context()) assert.Equal(t, "https://localhost/sub-path/avatars/avatar.png", link) } @@ -43,7 +42,7 @@ func TestUserAvatarGenerate(t *testing.T) { // there was no avatar, generate a new one assert.Empty(t, u.Avatar) - err = GenerateRandomAvatar(db.DefaultContext, u) + err = GenerateRandomAvatar(t.Context(), u) require.NoError(t, err) assert.NotEmpty(t, u.Avatar) @@ -56,7 +55,7 @@ func TestUserAvatarGenerate(t *testing.T) { require.NoError(t, err) // try to generate again - err = GenerateRandomAvatar(db.DefaultContext, u) + err = GenerateRandomAvatar(t.Context(), u) require.NoError(t, err) assert.Equal(t, oldAvatarPath, u.CustomAvatarRelativePath()) f, err := storage.Avatars.Open(u.CustomAvatarRelativePath()) diff --git a/models/user/email_address_test.go b/models/user/email_address_test.go index c0666246b04..6ef18fb0f64 100644 --- a/models/user/email_address_test.go +++ b/models/user/email_address_test.go @@ -18,14 +18,14 @@ import ( func TestGetEmailAddresses(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - emails, _ := user_model.GetEmailAddresses(db.DefaultContext, int64(1)) + emails, _ := user_model.GetEmailAddresses(t.Context(), int64(1)) if assert.Len(t, emails, 3) { assert.True(t, emails[0].IsPrimary) assert.True(t, emails[2].IsActivated) assert.False(t, emails[2].IsPrimary) } - emails, _ = user_model.GetEmailAddresses(db.DefaultContext, int64(2)) + emails, _ = user_model.GetEmailAddresses(t.Context(), int64(2)) if assert.Len(t, emails, 2) { assert.True(t, emails[0].IsPrimary) assert.True(t, emails[0].IsActivated) @@ -35,36 +35,36 @@ func TestGetEmailAddresses(t *testing.T) { func TestIsEmailUsed(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - isExist, _ := user_model.IsEmailUsed(db.DefaultContext, "") + isExist, _ := user_model.IsEmailUsed(t.Context(), "") assert.True(t, isExist) - isExist, _ = user_model.IsEmailUsed(db.DefaultContext, "user11@example.com") + isExist, _ = user_model.IsEmailUsed(t.Context(), "user11@example.com") assert.True(t, isExist) - isExist, _ = user_model.IsEmailUsed(db.DefaultContext, "user1234567890@example.com") + isExist, _ = user_model.IsEmailUsed(t.Context(), "user1234567890@example.com") assert.False(t, isExist) } func TestMakeEmailPrimary(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - err := user_model.MakeActiveEmailPrimary(db.DefaultContext, 9999999) + err := user_model.MakeActiveEmailPrimary(t.Context(), 9999999) assert.Error(t, err) assert.ErrorIs(t, err, user_model.ErrEmailAddressNotExist{}) email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user11@example.com"}) - err = user_model.MakeActiveEmailPrimary(db.DefaultContext, email.ID) + err = user_model.MakeActiveEmailPrimary(t.Context(), email.ID) assert.Error(t, err) assert.ErrorIs(t, err, user_model.ErrEmailAddressNotExist{}) // inactive email is considered as not exist for "MakeActiveEmailPrimary" email = unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user9999999@example.com"}) - err = user_model.MakeActiveEmailPrimary(db.DefaultContext, email.ID) + err = user_model.MakeActiveEmailPrimary(t.Context(), email.ID) assert.Error(t, err) assert.True(t, user_model.IsErrUserNotExist(err)) email = unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user101@example.com"}) - err = user_model.MakeActiveEmailPrimary(db.DefaultContext, email.ID) + err = user_model.MakeActiveEmailPrimary(t.Context(), email.ID) assert.NoError(t, err) - user, _ := user_model.GetUserByID(db.DefaultContext, int64(10)) + user, _ := user_model.GetUserByID(t.Context(), int64(10)) assert.Equal(t, "user101@example.com", user.Email) } @@ -76,9 +76,9 @@ func TestActivate(t *testing.T) { UID: int64(1), Email: "user11@example.com", } - assert.NoError(t, user_model.ActivateEmail(db.DefaultContext, email)) + assert.NoError(t, user_model.ActivateEmail(t.Context(), email)) - emails, _ := user_model.GetEmailAddresses(db.DefaultContext, int64(1)) + emails, _ := user_model.GetEmailAddresses(t.Context(), int64(1)) assert.Len(t, emails, 3) assert.True(t, emails[0].IsActivated) assert.True(t, emails[0].IsPrimary) @@ -96,7 +96,7 @@ func TestListEmails(t *testing.T) { PageSize: 10000, }, } - emails, count, err := user_model.SearchEmails(db.DefaultContext, opts) + emails, count, err := user_model.SearchEmails(t.Context(), opts) assert.NoError(t, err) assert.Greater(t, count, int64(5)) @@ -110,13 +110,13 @@ func TestListEmails(t *testing.T) { // Must find no records opts = &user_model.SearchEmailOptions{Keyword: "NOTFOUND"} - emails, count, err = user_model.SearchEmails(db.DefaultContext, opts) + emails, count, err = user_model.SearchEmails(t.Context(), opts) assert.NoError(t, err) assert.Equal(t, int64(0), count) // Must find users 'user2', 'user28', etc. opts = &user_model.SearchEmailOptions{Keyword: "user2"} - emails, count, err = user_model.SearchEmails(db.DefaultContext, opts) + emails, count, err = user_model.SearchEmails(t.Context(), opts) assert.NoError(t, err) assert.NotEqual(t, int64(0), count) assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 2 })) @@ -124,14 +124,14 @@ func TestListEmails(t *testing.T) { // Must find only primary addresses (i.e. from the `user` table) opts = &user_model.SearchEmailOptions{IsPrimary: optional.Some(true)} - emails, _, err = user_model.SearchEmails(db.DefaultContext, opts) + emails, _, err = user_model.SearchEmails(t.Context(), opts) assert.NoError(t, err) assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsPrimary })) assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsPrimary })) // Must find only inactive addresses (i.e. not validated) opts = &user_model.SearchEmailOptions{IsActivated: optional.Some(false)} - emails, _, err = user_model.SearchEmails(db.DefaultContext, opts) + emails, _, err = user_model.SearchEmails(t.Context(), opts) assert.NoError(t, err) assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsActivated })) assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsActivated })) @@ -143,7 +143,7 @@ func TestListEmails(t *testing.T) { Page: 1, }, } - emails, count, err = user_model.SearchEmails(db.DefaultContext, opts) + emails, count, err = user_model.SearchEmails(t.Context(), opts) assert.NoError(t, err) assert.Len(t, emails, 5) assert.Greater(t, count, int64(len(emails))) diff --git a/models/user/follow_test.go b/models/user/follow_test.go index c327d935aee..1d5f144164e 100644 --- a/models/user/follow_test.go +++ b/models/user/follow_test.go @@ -6,7 +6,6 @@ package user_test import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -15,9 +14,9 @@ import ( func TestIsFollowing(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.True(t, user_model.IsFollowing(db.DefaultContext, 4, 2)) - assert.False(t, user_model.IsFollowing(db.DefaultContext, 2, 4)) - assert.False(t, user_model.IsFollowing(db.DefaultContext, 5, unittest.NonexistentID)) - assert.False(t, user_model.IsFollowing(db.DefaultContext, unittest.NonexistentID, 5)) - assert.False(t, user_model.IsFollowing(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID)) + assert.True(t, user_model.IsFollowing(t.Context(), 4, 2)) + assert.False(t, user_model.IsFollowing(t.Context(), 2, 4)) + assert.False(t, user_model.IsFollowing(t.Context(), 5, unittest.NonexistentID)) + assert.False(t, user_model.IsFollowing(t.Context(), unittest.NonexistentID, 5)) + assert.False(t, user_model.IsFollowing(t.Context(), unittest.NonexistentID, unittest.NonexistentID)) } diff --git a/models/user/openid_test.go b/models/user/openid_test.go index 708af9e6530..fa260e7a9ea 100644 --- a/models/user/openid_test.go +++ b/models/user/openid_test.go @@ -6,7 +6,6 @@ package user_test import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -17,7 +16,7 @@ import ( func TestGetUserOpenIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - oids, err := user_model.GetUserOpenIDs(db.DefaultContext, int64(1)) + oids, err := user_model.GetUserOpenIDs(t.Context(), int64(1)) if assert.NoError(t, err) && assert.Len(t, oids, 2) { assert.Equal(t, "https://user1.domain1.tld/", oids[0].URI) assert.False(t, oids[0].Show) @@ -25,7 +24,7 @@ func TestGetUserOpenIDs(t *testing.T) { assert.True(t, oids[1].Show) } - oids, err = user_model.GetUserOpenIDs(db.DefaultContext, int64(2)) + oids, err = user_model.GetUserOpenIDs(t.Context(), int64(2)) if assert.NoError(t, err) && assert.Len(t, oids, 1) { assert.Equal(t, "https://domain1.tld/user2/", oids[0].URI) assert.True(t, oids[0].Show) @@ -34,23 +33,23 @@ func TestGetUserOpenIDs(t *testing.T) { func TestToggleUserOpenIDVisibility(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - oids, err := user_model.GetUserOpenIDs(db.DefaultContext, int64(2)) + oids, err := user_model.GetUserOpenIDs(t.Context(), int64(2)) require.NoError(t, err) require.Len(t, oids, 1) assert.True(t, oids[0].Show) - err = user_model.ToggleUserOpenIDVisibility(db.DefaultContext, oids[0].ID) + err = user_model.ToggleUserOpenIDVisibility(t.Context(), oids[0].ID) require.NoError(t, err) - oids, err = user_model.GetUserOpenIDs(db.DefaultContext, int64(2)) + oids, err = user_model.GetUserOpenIDs(t.Context(), int64(2)) require.NoError(t, err) require.Len(t, oids, 1) assert.False(t, oids[0].Show) - err = user_model.ToggleUserOpenIDVisibility(db.DefaultContext, oids[0].ID) + err = user_model.ToggleUserOpenIDVisibility(t.Context(), oids[0].ID) require.NoError(t, err) - oids, err = user_model.GetUserOpenIDs(db.DefaultContext, int64(2)) + oids, err = user_model.GetUserOpenIDs(t.Context(), int64(2)) require.NoError(t, err) if assert.Len(t, oids, 1) { assert.True(t, oids[0].Show) diff --git a/models/user/redirect_test.go b/models/user/redirect_test.go index 484c5a663fb..015eac06682 100644 --- a/models/user/redirect_test.go +++ b/models/user/redirect_test.go @@ -6,7 +6,6 @@ package user_test import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -16,10 +15,10 @@ import ( func TestLookupUserRedirect(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - userID, err := user_model.LookupUserRedirect(db.DefaultContext, "olduser1") + userID, err := user_model.LookupUserRedirect(t.Context(), "olduser1") assert.NoError(t, err) assert.EqualValues(t, 1, userID) - _, err = user_model.LookupUserRedirect(db.DefaultContext, "doesnotexist") + _, err = user_model.LookupUserRedirect(t.Context(), "doesnotexist") assert.True(t, user_model.IsErrUserRedirectNotExist(err)) } diff --git a/models/user/setting_test.go b/models/user/setting_test.go index 3c199013f39..7332e442b4c 100644 --- a/models/user/setting_test.go +++ b/models/user/setting_test.go @@ -6,7 +6,6 @@ package user_test import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -20,41 +19,41 @@ func TestSettings(t *testing.T) { newSetting := &user_model.Setting{UserID: 99, SettingKey: keyName, SettingValue: "Gitea User Setting Test"} // create setting - err := user_model.SetUserSetting(db.DefaultContext, newSetting.UserID, newSetting.SettingKey, newSetting.SettingValue) + err := user_model.SetUserSetting(t.Context(), newSetting.UserID, newSetting.SettingKey, newSetting.SettingValue) assert.NoError(t, err) // test about saving unchanged values - err = user_model.SetUserSetting(db.DefaultContext, newSetting.UserID, newSetting.SettingKey, newSetting.SettingValue) + err = user_model.SetUserSetting(t.Context(), newSetting.UserID, newSetting.SettingKey, newSetting.SettingValue) assert.NoError(t, err) // get specific setting - settings, err := user_model.GetSettings(db.DefaultContext, 99, []string{keyName}) + settings, err := user_model.GetSettings(t.Context(), 99, []string{keyName}) assert.NoError(t, err) assert.Len(t, settings, 1) assert.Equal(t, newSetting.SettingValue, settings[keyName].SettingValue) - settingValue, err := user_model.GetUserSetting(db.DefaultContext, 99, keyName) + settingValue, err := user_model.GetUserSetting(t.Context(), 99, keyName) assert.NoError(t, err) assert.Equal(t, newSetting.SettingValue, settingValue) - settingValue, err = user_model.GetUserSetting(db.DefaultContext, 99, "no_such") + settingValue, err = user_model.GetUserSetting(t.Context(), 99, "no_such") assert.NoError(t, err) assert.Empty(t, settingValue) // updated setting updatedSetting := &user_model.Setting{UserID: 99, SettingKey: keyName, SettingValue: "Updated"} - err = user_model.SetUserSetting(db.DefaultContext, updatedSetting.UserID, updatedSetting.SettingKey, updatedSetting.SettingValue) + err = user_model.SetUserSetting(t.Context(), updatedSetting.UserID, updatedSetting.SettingKey, updatedSetting.SettingValue) assert.NoError(t, err) // get all settings - settings, err = user_model.GetUserAllSettings(db.DefaultContext, 99) + settings, err = user_model.GetUserAllSettings(t.Context(), 99) assert.NoError(t, err) assert.Len(t, settings, 1) assert.Equal(t, updatedSetting.SettingValue, settings[updatedSetting.SettingKey].SettingValue) // delete setting - err = user_model.DeleteUserSetting(db.DefaultContext, 99, keyName) + err = user_model.DeleteUserSetting(t.Context(), 99, keyName) assert.NoError(t, err) - settings, err = user_model.GetUserAllSettings(db.DefaultContext, 99) + settings, err = user_model.GetUserAllSettings(t.Context(), 99) assert.NoError(t, err) assert.Empty(t, settings) } diff --git a/models/user/user.go b/models/user/user.go index c362cbc6d2b..ae500f3a1f2 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -27,6 +27,7 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/httplib" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/setting" @@ -303,8 +304,8 @@ func (u *User) HomeLink() string { } // HTMLURL returns the user or organization's full link. -func (u *User) HTMLURL() string { - return setting.AppURL + url.PathEscape(u.Name) +func (u *User) HTMLURL(ctx context.Context) string { + return httplib.MakeAbsoluteURL(ctx, u.HomeLink()) } // OrganisationLink returns the organization sub page link. @@ -955,6 +956,16 @@ func UpdateUserCols(ctx context.Context, u *User, cols ...string) error { return err } +// UpdateUserColsNoAutoTime update user according special columns +func UpdateUserColsNoAutoTime(ctx context.Context, u *User, cols ...string) error { + if err := ValidateUser(u, cols...); err != nil { + return err + } + + _, err := db.GetEngine(ctx).ID(u.ID).Cols(cols...).NoAutoTime().Update(u) + return err +} + // GetInactiveUsers gets all inactive users func GetInactiveUsers(ctx context.Context, olderThan time.Duration) ([]*User, error) { cond := builder.And( diff --git a/models/user/user_system_test.go b/models/user/user_system_test.go index 97768b509be..5aa3fa463c9 100644 --- a/models/user/user_system_test.go +++ b/models/user/user_system_test.go @@ -6,27 +6,25 @@ package user import ( "testing" - "code.gitea.io/gitea/models/db" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestSystemUser(t *testing.T) { - u, err := GetPossibleUserByID(db.DefaultContext, -1) + u, err := GetPossibleUserByID(t.Context(), -1) require.NoError(t, err) assert.Equal(t, "Ghost", u.Name) assert.Equal(t, "ghost", u.LowerName) assert.True(t, u.IsGhost()) assert.True(t, IsGhostUserName("gHost")) - u, err = GetPossibleUserByID(db.DefaultContext, -2) + u, err = GetPossibleUserByID(t.Context(), -2) require.NoError(t, err) assert.Equal(t, "gitea-actions", u.Name) assert.Equal(t, "gitea-actions", u.LowerName) assert.True(t, u.IsGiteaActions()) assert.True(t, IsGiteaActionsUserName("Gitea-actionS")) - _, err = GetPossibleUserByID(db.DefaultContext, -3) + _, err = GetPossibleUserByID(t.Context(), -3) require.Error(t, err) } diff --git a/models/user/user_test.go b/models/user/user_test.go index 7944fc4b734..4201ec4816c 100644 --- a/models/user/user_test.go +++ b/models/user/user_test.go @@ -44,7 +44,7 @@ func TestIsUsableUsername(t *testing.T) { func TestOAuth2Application_LoadUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) app := unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ID: 1}) - user, err := user_model.GetUserByID(db.DefaultContext, app.UID) + user, err := user_model.GetUserByID(t.Context(), app.UID) assert.NoError(t, err) assert.NotNil(t, user) } @@ -53,14 +53,14 @@ func TestUserEmails(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) t.Run("GetUserEmailsByNames", func(t *testing.T) { // ignore none active user email - assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"})) - assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"})) - assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "org7"})) + assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(t.Context(), []string{"user8", "user9"})) + assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(t.Context(), []string{"user8", "user5"})) + assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(t.Context(), []string{"user8", "org7"})) }) t.Run("GetUsersByEmails", func(t *testing.T) { defer test.MockVariableValue(&setting.Service.NoReplyAddress, "NoReply.gitea.internal")() testGetUserByEmail := func(t *testing.T, email string, uid int64) { - m, err := user_model.GetUsersByEmails(db.DefaultContext, []string{email}) + m, err := user_model.GetUsersByEmails(t.Context(), []string{email}) require.NoError(t, err) user := m.GetByEmail(email) if uid == 0 { @@ -114,7 +114,7 @@ func TestCanCreateOrganization(t *testing.T) { func TestSearchUsers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(opts user_model.SearchUserOptions, expectedUserOrOrgIDs []int64) { - users, _, err := user_model.SearchUsers(db.DefaultContext, opts) + users, _, err := user_model.SearchUsers(t.Context(), opts) assert.NoError(t, err) cassText := fmt.Sprintf("ids: %v, opts: %v", expectedUserOrOrgIDs, opts) if assert.Len(t, users, len(expectedUserOrOrgIDs), "case: %s", cassText) { @@ -243,7 +243,7 @@ func BenchmarkHashPassword(b *testing.B) { func TestNewGitSig(t *testing.T) { users := make([]*user_model.User, 0, 20) - err := db.GetEngine(db.DefaultContext).Find(&users) + err := db.GetEngine(t.Context()).Find(&users) assert.NoError(t, err) for _, user := range users { @@ -257,7 +257,7 @@ func TestNewGitSig(t *testing.T) { func TestDisplayName(t *testing.T) { users := make([]*user_model.User, 0, 20) - err := db.GetEngine(db.DefaultContext).Find(&users) + err := db.GetEngine(t.Context()).Find(&users) assert.NoError(t, err) for _, user := range users { @@ -280,7 +280,7 @@ func TestCreateUserInvalidEmail(t *testing.T) { MustChangePassword: false, } - err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{}) + err := user_model.CreateUser(t.Context(), user, &user_model.Meta{}) assert.Error(t, err) assert.True(t, user_model.IsErrEmailCharIsNotSupported(err)) } @@ -294,7 +294,7 @@ func TestCreateUserEmailAlreadyUsed(t *testing.T) { user.Name = "testuser" user.LowerName = strings.ToLower(user.Name) user.ID = 0 - err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{}) + err := user_model.CreateUser(t.Context(), user, &user_model.Meta{}) assert.Error(t, err) assert.True(t, user_model.IsErrEmailAlreadyUsed(err)) } @@ -311,7 +311,7 @@ func TestCreateUserCustomTimestamps(t *testing.T) { user.ID = 0 user.Email = "unique@example.com" user.CreatedUnix = creationTimestamp - err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{}) + err := user_model.CreateUser(t.Context(), user, &user_model.Meta{}) assert.NoError(t, err) fetched, err := user_model.GetUserByID(t.Context(), user.ID) @@ -336,7 +336,7 @@ func TestCreateUserWithoutCustomTimestamps(t *testing.T) { user.Email = "unique@example.com" user.CreatedUnix = 0 user.UpdatedUnix = 0 - err := user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{}) + err := user_model.CreateUser(t.Context(), user, &user_model.Meta{}) assert.NoError(t, err) timestampEnd := time.Now().Unix() @@ -355,12 +355,12 @@ func TestGetUserIDsByNames(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // ignore non existing - IDs, err := user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "user2", "none_existing_user"}, true) + IDs, err := user_model.GetUserIDsByNames(t.Context(), []string{"user1", "user2", "none_existing_user"}, true) assert.NoError(t, err) assert.Equal(t, []int64{1, 2}, IDs) // ignore non existing - IDs, err = user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "do_not_exist"}, false) + IDs, err = user_model.GetUserIDsByNames(t.Context(), []string{"user1", "do_not_exist"}, false) assert.Error(t, err) assert.Equal(t, []int64(nil), IDs) } @@ -368,14 +368,14 @@ func TestGetUserIDsByNames(t *testing.T) { func TestGetMaileableUsersByIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - results, err := user_model.GetMailableUsersByIDs(db.DefaultContext, []int64{1, 4}, false) + results, err := user_model.GetMailableUsersByIDs(t.Context(), []int64{1, 4}, false) assert.NoError(t, err) assert.Len(t, results, 1) if len(results) > 1 { assert.Equal(t, 1, results[0].ID) } - results, err = user_model.GetMailableUsersByIDs(db.DefaultContext, []int64{1, 4}, true) + results, err = user_model.GetMailableUsersByIDs(t.Context(), []int64{1, 4}, true) assert.NoError(t, err) assert.Len(t, results, 2) if len(results) > 2 { @@ -389,7 +389,7 @@ func TestNewUserRedirect(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "newusername")) + assert.NoError(t, user_model.NewUserRedirect(t.Context(), user.ID, user.Name, "newusername")) unittest.AssertExistsAndLoadBean(t, &user_model.Redirect{ LowerName: user.LowerName, @@ -406,7 +406,7 @@ func TestNewUserRedirect2(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "olduser1")) + assert.NoError(t, user_model.NewUserRedirect(t.Context(), user.ID, user.Name, "olduser1")) unittest.AssertExistsAndLoadBean(t, &user_model.Redirect{ LowerName: user.LowerName, @@ -423,7 +423,7 @@ func TestNewUserRedirect3(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "newusername")) + assert.NoError(t, user_model.NewUserRedirect(t.Context(), user.ID, user.Name, "newusername")) unittest.AssertExistsAndLoadBean(t, &user_model.Redirect{ LowerName: user.LowerName, @@ -434,17 +434,17 @@ func TestNewUserRedirect3(t *testing.T) { func TestGetUserByOpenID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - _, err := user_model.GetUserByOpenID(db.DefaultContext, "https://unknown") + _, err := user_model.GetUserByOpenID(t.Context(), "https://unknown") if assert.Error(t, err) { assert.True(t, user_model.IsErrUserNotExist(err)) } - user, err := user_model.GetUserByOpenID(db.DefaultContext, "https://user1.domain1.tld") + user, err := user_model.GetUserByOpenID(t.Context(), "https://user1.domain1.tld") if assert.NoError(t, err) { assert.Equal(t, int64(1), user.ID) } - user, err = user_model.GetUserByOpenID(db.DefaultContext, "https://domain1.tld/user2/") + user, err = user_model.GetUserByOpenID(t.Context(), "https://domain1.tld/user2/") if assert.NoError(t, err) { assert.Equal(t, int64(2), user.ID) } @@ -454,7 +454,7 @@ func TestFollowUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(follower, followed *user_model.User) { - assert.NoError(t, user_model.FollowUser(db.DefaultContext, follower, followed)) + assert.NoError(t, user_model.FollowUser(t.Context(), follower, followed)) unittest.AssertExistsAndLoadBean(t, &user_model.Follow{UserID: follower.ID, FollowID: followed.ID}) } @@ -465,7 +465,7 @@ func TestFollowUser(t *testing.T) { testSuccess(user4, user2) testSuccess(user5, user2) - assert.NoError(t, user_model.FollowUser(db.DefaultContext, user2, user2)) + assert.NoError(t, user_model.FollowUser(t.Context(), user2, user2)) unittest.CheckConsistencyFor(t, &user_model.User{}) } @@ -474,7 +474,7 @@ func TestUnfollowUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(followerID, followedID int64) { - assert.NoError(t, user_model.UnfollowUser(db.DefaultContext, followerID, followedID)) + assert.NoError(t, user_model.UnfollowUser(t.Context(), followerID, followedID)) unittest.AssertNotExistsBean(t, &user_model.Follow{UserID: followerID, FollowID: followedID}) } testSuccess(4, 2) @@ -501,7 +501,7 @@ func TestIsUserVisibleToViewer(t *testing.T) { } return u.Name } - assert.Equal(t, expected, user_model.IsUserVisibleToViewer(db.DefaultContext, u, viewer), "user %v should be visible to viewer %v: %v", name(u), name(viewer), expected) + assert.Equal(t, expected, user_model.IsUserVisibleToViewer(t.Context(), u, viewer), "user %v should be visible to viewer %v: %v", name(u), name(viewer), expected) } // admin viewer @@ -636,11 +636,11 @@ func TestGetInactiveUsers(t *testing.T) { // all inactive users // user1's createdunix is 1730468968 - users, err := user_model.GetInactiveUsers(db.DefaultContext, 0) + users, err := user_model.GetInactiveUsers(t.Context(), 0) assert.NoError(t, err) assert.Len(t, users, 1) interval := time.Now().Unix() - 1730468968 + 3600*24 - users, err = user_model.GetInactiveUsers(db.DefaultContext, time.Duration(interval*int64(time.Second))) + users, err = user_model.GetInactiveUsers(t.Context(), time.Duration(interval*int64(time.Second))) assert.NoError(t, err) assert.Empty(t, users) } diff --git a/models/webhook/webhook_system_test.go b/models/webhook/webhook_system_test.go index 96157ed9c9d..8aac693995d 100644 --- a/models/webhook/webhook_system_test.go +++ b/models/webhook/webhook_system_test.go @@ -6,7 +6,6 @@ package webhook import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/optional" @@ -16,20 +15,20 @@ import ( func TestGetSystemOrDefaultWebhooks(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := GetSystemOrDefaultWebhooks(db.DefaultContext, optional.None[bool]()) + hooks, err := GetSystemOrDefaultWebhooks(t.Context(), optional.None[bool]()) assert.NoError(t, err) if assert.Len(t, hooks, 2) { assert.Equal(t, int64(5), hooks[0].ID) assert.Equal(t, int64(6), hooks[1].ID) } - hooks, err = GetSystemOrDefaultWebhooks(db.DefaultContext, optional.Some(true)) + hooks, err = GetSystemOrDefaultWebhooks(t.Context(), optional.Some(true)) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(5), hooks[0].ID) } - hooks, err = GetSystemOrDefaultWebhooks(db.DefaultContext, optional.Some(false)) + hooks, err = GetSystemOrDefaultWebhooks(t.Context(), optional.Some(false)) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(6), hooks[0].ID) diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go index edad8fc996c..71f50017c51 100644 --- a/models/webhook/webhook_test.go +++ b/models/webhook/webhook_test.go @@ -31,7 +31,7 @@ func TestIsValidHookContentType(t *testing.T) { func TestWebhook_History(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) webhook := unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 1}) - tasks, err := webhook.History(db.DefaultContext, 0) + tasks, err := webhook.History(t.Context(), 0) assert.NoError(t, err) if assert.Len(t, tasks, 3) { assert.Equal(t, int64(3), tasks[0].ID) @@ -40,7 +40,7 @@ func TestWebhook_History(t *testing.T) { } webhook = unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 2}) - tasks, err = webhook.History(db.DefaultContext, 0) + tasks, err = webhook.History(t.Context(), 0) assert.NoError(t, err) assert.Empty(t, tasks) } @@ -95,35 +95,35 @@ func TestCreateWebhook(t *testing.T) { Events: `{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}`, } unittest.AssertNotExistsBean(t, hook) - assert.NoError(t, CreateWebhook(db.DefaultContext, hook)) + assert.NoError(t, CreateWebhook(t.Context(), hook)) unittest.AssertExistsAndLoadBean(t, hook) } func TestGetWebhookByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hook, err := GetWebhookByRepoID(db.DefaultContext, 1, 1) + hook, err := GetWebhookByRepoID(t.Context(), 1, 1) assert.NoError(t, err) assert.Equal(t, int64(1), hook.ID) - _, err = GetWebhookByRepoID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) + _, err = GetWebhookByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID) assert.Error(t, err) assert.True(t, IsErrWebhookNotExist(err)) } func TestGetWebhookByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hook, err := GetWebhookByOwnerID(db.DefaultContext, 3, 3) + hook, err := GetWebhookByOwnerID(t.Context(), 3, 3) assert.NoError(t, err) assert.Equal(t, int64(3), hook.ID) - _, err = GetWebhookByOwnerID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) + _, err = GetWebhookByOwnerID(t.Context(), unittest.NonexistentID, unittest.NonexistentID) assert.Error(t, err) assert.True(t, IsErrWebhookNotExist(err)) } func TestGetActiveWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: optional.Some(true)}) + hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{RepoID: 1, IsActive: optional.Some(true)}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(1), hooks[0].ID) @@ -133,7 +133,7 @@ func TestGetActiveWebhooksByRepoID(t *testing.T) { func TestGetWebhooksByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1}) + hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{RepoID: 1}) assert.NoError(t, err) if assert.Len(t, hooks, 2) { assert.Equal(t, int64(1), hooks[0].ID) @@ -143,7 +143,7 @@ func TestGetWebhooksByRepoID(t *testing.T) { func TestGetActiveWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3, IsActive: optional.Some(true)}) + hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{OwnerID: 3, IsActive: optional.Some(true)}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(3), hooks[0].ID) @@ -153,7 +153,7 @@ func TestGetActiveWebhooksByOwnerID(t *testing.T) { func TestGetWebhooksByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3}) + hooks, err := db.Find[Webhook](t.Context(), ListWebhookOptions{OwnerID: 3}) assert.NoError(t, err) if assert.Len(t, hooks, 1) { assert.Equal(t, int64(3), hooks[0].ID) @@ -167,17 +167,17 @@ func TestUpdateWebhook(t *testing.T) { hook.IsActive = true hook.ContentType = ContentTypeForm unittest.AssertNotExistsBean(t, hook) - assert.NoError(t, UpdateWebhook(db.DefaultContext, hook)) + assert.NoError(t, UpdateWebhook(t.Context(), hook)) unittest.AssertExistsAndLoadBean(t, hook) } func TestDeleteWebhookByRepoID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 2, RepoID: 1}) - assert.NoError(t, DeleteWebhookByRepoID(db.DefaultContext, 1, 2)) + assert.NoError(t, DeleteWebhookByRepoID(t.Context(), 1, 2)) unittest.AssertNotExistsBean(t, &Webhook{ID: 2, RepoID: 1}) - err := DeleteWebhookByRepoID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) + err := DeleteWebhookByRepoID(t.Context(), unittest.NonexistentID, unittest.NonexistentID) assert.Error(t, err) assert.True(t, IsErrWebhookNotExist(err)) } @@ -185,17 +185,17 @@ func TestDeleteWebhookByRepoID(t *testing.T) { func TestDeleteWebhookByOwnerID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) unittest.AssertExistsAndLoadBean(t, &Webhook{ID: 3, OwnerID: 3}) - assert.NoError(t, DeleteWebhookByOwnerID(db.DefaultContext, 3, 3)) + assert.NoError(t, DeleteWebhookByOwnerID(t.Context(), 3, 3)) unittest.AssertNotExistsBean(t, &Webhook{ID: 3, OwnerID: 3}) - err := DeleteWebhookByOwnerID(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID) + err := DeleteWebhookByOwnerID(t.Context(), unittest.NonexistentID, unittest.NonexistentID) assert.Error(t, err) assert.True(t, IsErrWebhookNotExist(err)) } func TestHookTasks(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - hookTasks, err := HookTasks(db.DefaultContext, 1, 1) + hookTasks, err := HookTasks(t.Context(), 1, 1) assert.NoError(t, err) if assert.Len(t, hookTasks, 3) { assert.Equal(t, int64(3), hookTasks[0].ID) @@ -203,7 +203,7 @@ func TestHookTasks(t *testing.T) { assert.Equal(t, int64(1), hookTasks[2].ID) } - hookTasks, err = HookTasks(db.DefaultContext, unittest.NonexistentID, 1) + hookTasks, err = HookTasks(t.Context(), unittest.NonexistentID, 1) assert.NoError(t, err) assert.Empty(t, hookTasks) } @@ -215,7 +215,7 @@ func TestCreateHookTask(t *testing.T) { PayloadVersion: 2, } unittest.AssertNotExistsBean(t, hookTask) - _, err := CreateHookTask(db.DefaultContext, hookTask) + _, err := CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, hookTask) } @@ -227,7 +227,7 @@ func TestUpdateHookTask(t *testing.T) { hook.PayloadContent = "new payload content" hook.IsDelivered = true unittest.AssertNotExistsBean(t, hook) - assert.NoError(t, UpdateHookTask(db.DefaultContext, hook)) + assert.NoError(t, UpdateHookTask(t.Context(), hook)) unittest.AssertExistsAndLoadBean(t, hook) } @@ -240,7 +240,7 @@ func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) { PayloadVersion: 2, } unittest.AssertNotExistsBean(t, hookTask) - _, err := CreateHookTask(db.DefaultContext, hookTask) + _, err := CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, hookTask) @@ -256,7 +256,7 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) { PayloadVersion: 2, } unittest.AssertNotExistsBean(t, hookTask) - _, err := CreateHookTask(db.DefaultContext, hookTask) + _, err := CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, hookTask) @@ -273,7 +273,7 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) { PayloadVersion: 2, } unittest.AssertNotExistsBean(t, hookTask) - _, err := CreateHookTask(db.DefaultContext, hookTask) + _, err := CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, hookTask) @@ -290,7 +290,7 @@ func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) { PayloadVersion: 2, } unittest.AssertNotExistsBean(t, hookTask) - _, err := CreateHookTask(db.DefaultContext, hookTask) + _, err := CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, hookTask) @@ -306,7 +306,7 @@ func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) { PayloadVersion: 2, } unittest.AssertNotExistsBean(t, hookTask) - _, err := CreateHookTask(db.DefaultContext, hookTask) + _, err := CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, hookTask) @@ -323,7 +323,7 @@ func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *test PayloadVersion: 2, } unittest.AssertNotExistsBean(t, hookTask) - _, err := CreateHookTask(db.DefaultContext, hookTask) + _, err := CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, hookTask) diff --git a/modules/activitypub/client_test.go b/modules/activitypub/client_test.go index d0c48454457..361270a8005 100644 --- a/modules/activitypub/client_test.go +++ b/modules/activitypub/client_test.go @@ -10,7 +10,6 @@ import ( "net/http/httptest" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" @@ -22,7 +21,7 @@ func TestActivityPubSignedPost(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) pubID := "https://example.com/pubID" - c, err := NewClient(db.DefaultContext, user, pubID) + c, err := NewClient(t.Context(), user, pubID) assert.NoError(t, err) expected := "BODY" diff --git a/modules/activitypub/user_settings_test.go b/modules/activitypub/user_settings_test.go index 55862357f16..105d4aedea1 100644 --- a/modules/activitypub/user_settings_test.go +++ b/modules/activitypub/user_settings_test.go @@ -6,7 +6,6 @@ package activitypub import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -18,12 +17,12 @@ import ( func TestUserSettings(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - pub, priv, err := GetKeyPair(db.DefaultContext, user1) + pub, priv, err := GetKeyPair(t.Context(), user1) assert.NoError(t, err) - pub1, err := GetPublicKey(db.DefaultContext, user1) + pub1, err := GetPublicKey(t.Context(), user1) assert.NoError(t, err) assert.Equal(t, pub, pub1) - priv1, err := GetPrivateKey(db.DefaultContext, user1) + priv1, err := GetPrivateKey(t.Context(), user1) assert.NoError(t, err) assert.Equal(t, priv, priv1) } diff --git a/modules/git/attribute/main_test.go b/modules/git/attribute/main_test.go index df8241bfb08..1f1d80ec0a6 100644 --- a/modules/git/attribute/main_test.go +++ b/modules/git/attribute/main_test.go @@ -4,7 +4,6 @@ package attribute import ( - "context" "fmt" "os" "testing" @@ -22,7 +21,7 @@ func testRun(m *testing.M) error { defer util.RemoveAll(gitHomePath) setting.Git.HomePath = gitHomePath - if err = git.InitFull(context.Background()); err != nil { + if err = git.InitFull(); err != nil { return fmt.Errorf("failed to call Init: %w", err) } diff --git a/modules/git/blame.go b/modules/git/blame.go index 659dec34a1e..db10df129e2 100644 --- a/modules/git/blame.go +++ b/modules/git/blame.go @@ -141,7 +141,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath } }() - cmd := NewCommandNoGlobals("blame", "--porcelain") + cmd := NewCommand("blame", "--porcelain") if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore { ignoreRevsFileName, ignoreRevsFileCleanup, err = tryCreateBlameIgnoreRevsFile(commit) diff --git a/modules/git/blob_test.go b/modules/git/blob_test.go index f21e8d146d7..4c86aa70ba7 100644 --- a/modules/git/blob_test.go +++ b/modules/git/blob_test.go @@ -16,7 +16,7 @@ import ( func TestBlob_Data(t *testing.T) { output := "file2\n" bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - repo, err := openRepositoryWithDefaultContext(bareRepo1Path) + repo, err := OpenRepository(t.Context(), bareRepo1Path) require.NoError(t, err) defer repo.Close() @@ -36,7 +36,7 @@ func TestBlob_Data(t *testing.T) { func Benchmark_Blob_Data(b *testing.B) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - repo, err := openRepositoryWithDefaultContext(bareRepo1Path) + repo, err := OpenRepository(b.Context(), bareRepo1Path) if err != nil { b.Fatal(err) } diff --git a/modules/git/command.go b/modules/git/command.go index 22f1d023391..eeb987feb0b 100644 --- a/modules/git/command.go +++ b/modules/git/command.go @@ -29,25 +29,19 @@ import ( // In most cases, it shouldn't be used. Use AddXxx function instead type TrustedCmdArgs []internal.CmdArg -var ( - // globalCommandArgs global command args for external package setting - globalCommandArgs TrustedCmdArgs - - // defaultCommandExecutionTimeout default command execution timeout duration - defaultCommandExecutionTimeout = 360 * time.Second -) +// defaultCommandExecutionTimeout default command execution timeout duration +var defaultCommandExecutionTimeout = 360 * time.Second // DefaultLocale is the default LC_ALL to run git commands in. const DefaultLocale = "C" // Command represents a command with its subcommands or arguments. type Command struct { - prog string - args []string - globalArgsLength int - brokenArgs []string - cmd *exec.Cmd // for debug purpose only - configArgs []string + prog string + args []string + brokenArgs []string + cmd *exec.Cmd // for debug purpose only + configArgs []string } func logArgSanitize(arg string) string { @@ -72,10 +66,7 @@ func (c *Command) LogString() string { } a := make([]string, 0, len(c.args)+1) a = append(a, debugQuote(c.prog)) - if c.globalArgsLength > 0 { - a = append(a, "...global...") - } - for i := c.globalArgsLength; i < len(c.args); i++ { + for i := 0; i < len(c.args); i++ { a = append(a, debugQuote(logArgSanitize(c.args[i]))) } return strings.Join(a, " ") @@ -91,24 +82,6 @@ func (c *Command) ProcessState() string { // NewCommand creates and returns a new Git Command based on given command and arguments. // Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead. func NewCommand(args ...internal.CmdArg) *Command { - // Make an explicit copy of globalCommandArgs, otherwise append might overwrite it - cargs := make([]string, 0, len(globalCommandArgs)+len(args)) - for _, arg := range globalCommandArgs { - cargs = append(cargs, string(arg)) - } - for _, arg := range args { - cargs = append(cargs, string(arg)) - } - return &Command{ - prog: GitExecutable, - args: cargs, - globalArgsLength: len(globalCommandArgs), - } -} - -// NewCommandNoGlobals creates and returns a new Git Command based on given command and arguments only with the specified args and don't use global command args -// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead. -func NewCommandNoGlobals(args ...internal.CmdArg) *Command { cargs := make([]string, 0, len(args)) for _, arg := range args { cargs = append(cargs, string(arg)) @@ -468,19 +441,3 @@ func (c *Command) runStdBytes(ctx context.Context, opts *RunOpts) (stdout, stder // even if there is no err, there could still be some stderr output return stdoutBuf.Bytes(), stderr, nil } - -// AllowLFSFiltersArgs return globalCommandArgs with lfs filter, it should only be used for tests -func AllowLFSFiltersArgs() TrustedCmdArgs { - // Now here we should explicitly allow lfs filters to run - filteredLFSGlobalArgs := make(TrustedCmdArgs, len(globalCommandArgs)) - j := 0 - for _, arg := range globalCommandArgs { - if strings.Contains(string(arg), "lfs") { - j-- - } else { - filteredLFSGlobalArgs[j] = arg - j++ - } - } - return filteredLFSGlobalArgs[:j] -} diff --git a/modules/git/command_test.go b/modules/git/command_test.go index eb112707e78..85976e289ef 100644 --- a/modules/git/command_test.go +++ b/modules/git/command_test.go @@ -53,9 +53,9 @@ func TestGitArgument(t *testing.T) { } func TestCommandString(t *testing.T) { - cmd := NewCommandNoGlobals("a", "-m msg", "it's a test", `say "hello"`) + cmd := NewCommand("a", "-m msg", "it's a test", `say "hello"`) assert.Equal(t, cmd.prog+` a "-m msg" "it's a test" "say \"hello\""`, cmd.LogString()) - cmd = NewCommandNoGlobals("url: https://a:b@c/", "/root/dir-a/dir-b") + cmd = NewCommand("url: https://a:b@c/", "/root/dir-a/dir-b") assert.Equal(t, cmd.prog+` "url: https://sanitized-credential@c/" .../dir-a/dir-b`, cmd.LogString()) } diff --git a/modules/git/commit.go b/modules/git/commit.go index aae40c575bc..0dc894d3ab6 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -86,18 +86,13 @@ func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) { } // AddChanges marks local changes to be ready for commit. -func AddChanges(repoPath string, all bool, files ...string) error { - return AddChangesWithArgs(repoPath, globalCommandArgs, all, files...) -} - -// AddChangesWithArgs marks local changes to be ready for commit. -func AddChangesWithArgs(repoPath string, globalArgs TrustedCmdArgs, all bool, files ...string) error { - cmd := NewCommandNoGlobals(globalArgs...).AddArguments("add") +func AddChanges(ctx context.Context, repoPath string, all bool, files ...string) error { + cmd := NewCommand().AddArguments("add") if all { cmd.AddArguments("--all") } cmd.AddDashesAndList(files...) - _, _, err := cmd.RunStdString(DefaultContext, &RunOpts{Dir: repoPath}) + _, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) return err } @@ -110,16 +105,8 @@ type CommitChangesOptions struct { // CommitChanges commits local changes with given committer, author and message. // If author is nil, it will be the same as committer. -func CommitChanges(repoPath string, opts CommitChangesOptions) error { - cargs := make(TrustedCmdArgs, len(globalCommandArgs)) - copy(cargs, globalCommandArgs) - return CommitChangesWithArgs(repoPath, cargs, opts) -} - -// CommitChangesWithArgs commits local changes with given committer, author and message. -// If author is nil, it will be the same as committer. -func CommitChangesWithArgs(repoPath string, args TrustedCmdArgs, opts CommitChangesOptions) error { - cmd := NewCommandNoGlobals(args...) +func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptions) error { + cmd := NewCommand() if opts.Committer != nil { cmd.AddOptionValues("-c", "user.name="+opts.Committer.Name) cmd.AddOptionValues("-c", "user.email="+opts.Committer.Email) @@ -134,7 +121,7 @@ func CommitChangesWithArgs(repoPath string, args TrustedCmdArgs, opts CommitChan } cmd.AddOptionFormat("--message=%s", opts.Message) - _, _, err := cmd.RunStdString(DefaultContext, &RunOpts{Dir: repoPath}) + _, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) // No stderr but exit status 1 means nothing to commit. if err != nil && err.Error() == "exit status 1" { return nil diff --git a/modules/git/commit_info_test.go b/modules/git/commit_info_test.go index 078b6815d28..51e1551d2d3 100644 --- a/modules/git/commit_info_test.go +++ b/modules/git/commit_info_test.go @@ -18,7 +18,7 @@ const ( func cloneRepo(tb testing.TB, url string) (string, error) { repoDir := tb.TempDir() - if err := Clone(DefaultContext, url, repoDir, CloneRepoOptions{ + if err := Clone(tb.Context(), url, repoDir, CloneRepoOptions{ Mirror: false, Bare: false, Quiet: true, @@ -104,7 +104,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) { func TestEntries_GetCommitsInfo(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -114,7 +114,7 @@ func TestEntries_GetCommitsInfo(t *testing.T) { if err != nil { assert.NoError(t, err) } - clonedRepo1, err := openRepositoryWithDefaultContext(clonedPath) + clonedRepo1, err := OpenRepository(t.Context(), clonedPath) if err != nil { assert.NoError(t, err) } @@ -163,7 +163,7 @@ func BenchmarkEntries_GetCommitsInfo(b *testing.B) { b.Fatal(err) } - if repo, err = openRepositoryWithDefaultContext(repoPath); err != nil { + if repo, err = OpenRepository(b.Context(), repoPath); err != nil { b.Fatal(err) } defer repo.Close() diff --git a/modules/git/commit_sha256_test.go b/modules/git/commit_sha256_test.go index 97ccecdaccf..772f5eedb27 100644 --- a/modules/git/commit_sha256_test.go +++ b/modules/git/commit_sha256_test.go @@ -17,7 +17,7 @@ import ( func TestCommitsCountSha256(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256") - commitsCount, err := CommitsCount(DefaultContext, + commitsCount, err := CommitsCount(t.Context(), CommitsCountOptions{ RepoPath: bareRepo1Path, Revision: []string{"f004f41359117d319dedd0eaab8c5259ee2263da839dcba33637997458627fdc"}, @@ -30,7 +30,7 @@ func TestCommitsCountSha256(t *testing.T) { func TestCommitsCountWithoutBaseSha256(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256") - commitsCount, err := CommitsCount(DefaultContext, + commitsCount, err := CommitsCount(t.Context(), CommitsCountOptions{ RepoPath: bareRepo1Path, Not: "main", @@ -44,7 +44,7 @@ func TestCommitsCountWithoutBaseSha256(t *testing.T) { func TestGetFullCommitIDSha256(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256") - id, err := GetFullCommitID(DefaultContext, bareRepo1Path, "f004f4") + id, err := GetFullCommitID(t.Context(), bareRepo1Path, "f004f4") assert.NoError(t, err) assert.Equal(t, "f004f41359117d319dedd0eaab8c5259ee2263da839dcba33637997458627fdc", id) } @@ -52,7 +52,7 @@ func TestGetFullCommitIDSha256(t *testing.T) { func TestGetFullCommitIDErrorSha256(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256") - id, err := GetFullCommitID(DefaultContext, bareRepo1Path, "unknown") + id, err := GetFullCommitID(t.Context(), bareRepo1Path, "unknown") assert.Empty(t, id) if assert.Error(t, err) { assert.EqualError(t, err, "object does not exist [id: unknown, rel_path: ]") @@ -87,7 +87,7 @@ signed commit` 0x94, 0x33, 0xb2, 0xa6, 0x2b, 0x96, 0x4c, 0x17, 0xa4, 0x48, 0x5a, 0xe1, 0x80, 0xf4, 0x5f, 0x59, 0x5d, 0x3e, 0x69, 0xd3, 0x1b, 0x78, 0x60, 0x87, 0x77, 0x5e, 0x28, 0xc6, 0xb6, 0x39, 0x9d, 0xf0, } - gitRepo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare_sha256")) + gitRepo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "repo1_bare_sha256")) assert.NoError(t, err) assert.NotNil(t, gitRepo) defer gitRepo.Close() @@ -130,7 +130,7 @@ signed commit`, commitFromReader.Signature.Payload) func TestHasPreviousCommitSha256(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256") - repo, err := openRepositoryWithDefaultContext(bareRepo1Path) + repo, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer repo.Close() @@ -161,7 +161,7 @@ func TestHasPreviousCommitSha256(t *testing.T) { func TestGetCommitFileStatusMergesSha256(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo6_merge_sha256") - commitFileStatus, err := GetCommitFileStatus(DefaultContext, bareRepo1Path, "d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1") + commitFileStatus, err := GetCommitFileStatus(t.Context(), bareRepo1Path, "d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1") assert.NoError(t, err) expected := CommitFileStatus{ @@ -186,7 +186,7 @@ func TestGetCommitFileStatusMergesSha256(t *testing.T) { []string{}, } - commitFileStatus, err = GetCommitFileStatus(DefaultContext, bareRepo1Path, "da1ded40dc8e5b7c564171f4bf2fc8370487decfb1cb6a99ef28f3ed73d09172") + commitFileStatus, err = GetCommitFileStatus(t.Context(), bareRepo1Path, "da1ded40dc8e5b7c564171f4bf2fc8370487decfb1cb6a99ef28f3ed73d09172") assert.NoError(t, err) assert.Equal(t, expected.Added, commitFileStatus.Added) diff --git a/modules/git/commit_test.go b/modules/git/commit_test.go index 81fb91dfc61..688b4e294f5 100644 --- a/modules/git/commit_test.go +++ b/modules/git/commit_test.go @@ -16,7 +16,7 @@ import ( func TestCommitsCount(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - commitsCount, err := CommitsCount(DefaultContext, + commitsCount, err := CommitsCount(t.Context(), CommitsCountOptions{ RepoPath: bareRepo1Path, Revision: []string{"8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"}, @@ -29,7 +29,7 @@ func TestCommitsCount(t *testing.T) { func TestCommitsCountWithoutBase(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - commitsCount, err := CommitsCount(DefaultContext, + commitsCount, err := CommitsCount(t.Context(), CommitsCountOptions{ RepoPath: bareRepo1Path, Not: "master", @@ -43,7 +43,7 @@ func TestCommitsCountWithoutBase(t *testing.T) { func TestGetFullCommitID(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - id, err := GetFullCommitID(DefaultContext, bareRepo1Path, "8006ff9a") + id, err := GetFullCommitID(t.Context(), bareRepo1Path, "8006ff9a") assert.NoError(t, err) assert.Equal(t, "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0", id) } @@ -51,7 +51,7 @@ func TestGetFullCommitID(t *testing.T) { func TestGetFullCommitIDError(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - id, err := GetFullCommitID(DefaultContext, bareRepo1Path, "unknown") + id, err := GetFullCommitID(t.Context(), bareRepo1Path, "unknown") assert.Empty(t, id) if assert.Error(t, err) { assert.EqualError(t, err, "object does not exist [id: unknown, rel_path: ]") @@ -83,7 +83,7 @@ gpgsig -----BEGIN PGP SIGNATURE----- empty commit` sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2} - gitRepo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare")) + gitRepo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "repo1_bare")) assert.NoError(t, err) assert.NotNil(t, gitRepo) defer gitRepo.Close() @@ -147,7 +147,7 @@ gpgsig -----BEGIN PGP SIGNATURE----- ISO-8859-1` commitString = strings.ReplaceAll(commitString, "", " ") sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2} - gitRepo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare")) + gitRepo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "repo1_bare")) assert.NoError(t, err) assert.NotNil(t, gitRepo) defer gitRepo.Close() @@ -189,7 +189,7 @@ ISO-8859-1`, commitFromReader.Signature.Payload) func TestHasPreviousCommit(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - repo, err := openRepositoryWithDefaultContext(bareRepo1Path) + repo, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer repo.Close() @@ -320,7 +320,7 @@ func TestParseCommitFileStatus(t *testing.T) { func TestGetCommitFileStatusMerges(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo6_merge") - commitFileStatus, err := GetCommitFileStatus(DefaultContext, bareRepo1Path, "022f4ce6214973e018f02bf363bf8a2e3691f699") + commitFileStatus, err := GetCommitFileStatus(t.Context(), bareRepo1Path, "022f4ce6214973e018f02bf363bf8a2e3691f699") assert.NoError(t, err) expected := CommitFileStatus{ diff --git a/modules/git/config.go b/modules/git/config.go index 234be7b9557..3a717908b9b 100644 --- a/modules/git/config.go +++ b/modules/git/config.go @@ -4,6 +4,7 @@ package git import ( + "context" "fmt" "os" "regexp" @@ -14,7 +15,7 @@ import ( ) // syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem) -func syncGitConfig() (err error) { +func syncGitConfig(ctx context.Context) (err error) { if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil { return fmt.Errorf("unable to prepare git home directory %s, err: %w", HomeDir(), err) } @@ -22,7 +23,7 @@ func syncGitConfig() (err error) { // first, write user's git config options to git config file // user config options could be overwritten by builtin values later, because if a value is builtin, it must have some special purposes for k, v := range setting.GitConfig.Options { - if err = configSet(strings.ToLower(k), v); err != nil { + if err = configSet(ctx, strings.ToLower(k), v); err != nil { return err } } @@ -34,41 +35,41 @@ func syncGitConfig() (err error) { "user.name": "Gitea", "user.email": "gitea@fake.local", } { - if err := configSetNonExist(configKey, defaultValue); err != nil { + if err := configSetNonExist(ctx, configKey, defaultValue); err != nil { return err } } // Set git some configurations - these must be set to these values for gitea to work correctly - if err := configSet("core.quotePath", "false"); err != nil { + if err := configSet(ctx, "core.quotePath", "false"); err != nil { return err } if DefaultFeatures().CheckVersionAtLeast("2.10") { - if err := configSet("receive.advertisePushOptions", "true"); err != nil { + if err := configSet(ctx, "receive.advertisePushOptions", "true"); err != nil { return err } } if DefaultFeatures().CheckVersionAtLeast("2.18") { - if err := configSet("core.commitGraph", "true"); err != nil { + if err := configSet(ctx, "core.commitGraph", "true"); err != nil { return err } - if err := configSet("gc.writeCommitGraph", "true"); err != nil { + if err := configSet(ctx, "gc.writeCommitGraph", "true"); err != nil { return err } - if err := configSet("fetch.writeCommitGraph", "true"); err != nil { + if err := configSet(ctx, "fetch.writeCommitGraph", "true"); err != nil { return err } } if DefaultFeatures().SupportProcReceive { // set support for AGit flow - if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil { + if err := configAddNonExist(ctx, "receive.procReceiveRefs", "refs/for"); err != nil { return err } } else { - if err := configUnsetAll("receive.procReceiveRefs", "refs/for"); err != nil { + if err := configUnsetAll(ctx, "receive.procReceiveRefs", "refs/for"); err != nil { return err } } @@ -81,18 +82,18 @@ func syncGitConfig() (err error) { // As Gitea now always use its internal git config file, and access to the git repositories is managed through Gitea, // it is now safe to set "safe.directory=*" for internal usage only. // Although this setting is only supported by some new git versions, it is also tolerated by earlier versions - if err := configAddNonExist("safe.directory", "*"); err != nil { + if err := configAddNonExist(ctx, "safe.directory", "*"); err != nil { return err } if runtime.GOOS == "windows" { - if err := configSet("core.longpaths", "true"); err != nil { + if err := configSet(ctx, "core.longpaths", "true"); err != nil { return err } if setting.Git.DisableCoreProtectNTFS { - err = configSet("core.protectNTFS", "false") + err = configSet(ctx, "core.protectNTFS", "false") } else { - err = configUnsetAll("core.protectNTFS", "false") + err = configUnsetAll(ctx, "core.protectNTFS", "false") } if err != nil { return err @@ -101,22 +102,22 @@ func syncGitConfig() (err error) { // By default partial clones are disabled, enable them from git v2.22 if !setting.Git.DisablePartialClone && DefaultFeatures().CheckVersionAtLeast("2.22") { - if err = configSet("uploadpack.allowfilter", "true"); err != nil { + if err = configSet(ctx, "uploadpack.allowfilter", "true"); err != nil { return err } - err = configSet("uploadpack.allowAnySHA1InWant", "true") + err = configSet(ctx, "uploadpack.allowAnySHA1InWant", "true") } else { - if err = configUnsetAll("uploadpack.allowfilter", "true"); err != nil { + if err = configUnsetAll(ctx, "uploadpack.allowfilter", "true"); err != nil { return err } - err = configUnsetAll("uploadpack.allowAnySHA1InWant", "true") + err = configUnsetAll(ctx, "uploadpack.allowAnySHA1InWant", "true") } return err } -func configSet(key, value string) error { - stdout, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(DefaultContext, nil) +func configSet(ctx context.Context, key, value string) error { + stdout, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) if err != nil && !IsErrorExitCode(err, 1) { return fmt.Errorf("failed to get git config %s, err: %w", key, err) } @@ -126,7 +127,7 @@ func configSet(key, value string) error { return nil } - _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(DefaultContext, nil) + _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to set git global config %s, err: %w", key, err) } @@ -134,15 +135,15 @@ func configSet(key, value string) error { return nil } -func configSetNonExist(key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(DefaultContext, nil) +func configSetNonExist(ctx context.Context, key, value string) error { + _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) if err == nil { // already exist return nil } if IsErrorExitCode(err, 1) { // not exist, set new config - _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(DefaultContext, nil) + _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to set git global config %s, err: %w", key, err) } @@ -152,15 +153,15 @@ func configSetNonExist(key, value string) error { return fmt.Errorf("failed to get git config %s, err: %w", key, err) } -func configAddNonExist(key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(DefaultContext, nil) +func configAddNonExist(ctx context.Context, key, value string) error { + _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) if err == nil { // already exist return nil } if IsErrorExitCode(err, 1) { // not exist, add new config - _, _, err = NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(DefaultContext, nil) + _, _, err = NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to add git global config %s, err: %w", key, err) } @@ -169,11 +170,11 @@ func configAddNonExist(key, value string) error { return fmt.Errorf("failed to get git config %s, err: %w", key, err) } -func configUnsetAll(key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(DefaultContext, nil) +func configUnsetAll(ctx context.Context, key, value string) error { + _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) if err == nil { // exist, need to remove - _, _, err = NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(DefaultContext, nil) + _, _, err = NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to unset git global config %s, err: %w", key, err) } diff --git a/modules/git/config_test.go b/modules/git/config_test.go index 59f70c99e2f..911e0e01845 100644 --- a/modules/git/config_test.go +++ b/modules/git/config_test.go @@ -21,35 +21,36 @@ func gitConfigContains(sub string) bool { } func TestGitConfig(t *testing.T) { + ctx := t.Context() assert.False(t, gitConfigContains("key-a")) - assert.NoError(t, configSetNonExist("test.key-a", "val-a")) + assert.NoError(t, configSetNonExist(ctx, "test.key-a", "val-a")) assert.True(t, gitConfigContains("key-a = val-a")) - assert.NoError(t, configSetNonExist("test.key-a", "val-a-changed")) + assert.NoError(t, configSetNonExist(ctx, "test.key-a", "val-a-changed")) assert.False(t, gitConfigContains("key-a = val-a-changed")) - assert.NoError(t, configSet("test.key-a", "val-a-changed")) + assert.NoError(t, configSet(ctx, "test.key-a", "val-a-changed")) assert.True(t, gitConfigContains("key-a = val-a-changed")) - assert.NoError(t, configAddNonExist("test.key-b", "val-b")) + assert.NoError(t, configAddNonExist(ctx, "test.key-b", "val-b")) assert.True(t, gitConfigContains("key-b = val-b")) - assert.NoError(t, configAddNonExist("test.key-b", "val-2b")) + assert.NoError(t, configAddNonExist(ctx, "test.key-b", "val-2b")) assert.True(t, gitConfigContains("key-b = val-b")) assert.True(t, gitConfigContains("key-b = val-2b")) - assert.NoError(t, configUnsetAll("test.key-b", "val-b")) + assert.NoError(t, configUnsetAll(ctx, "test.key-b", "val-b")) assert.False(t, gitConfigContains("key-b = val-b")) assert.True(t, gitConfigContains("key-b = val-2b")) - assert.NoError(t, configUnsetAll("test.key-b", "val-2b")) + assert.NoError(t, configUnsetAll(ctx, "test.key-b", "val-2b")) assert.False(t, gitConfigContains("key-b = val-2b")) - assert.NoError(t, configSet("test.key-x", "*")) + assert.NoError(t, configSet(ctx, "test.key-x", "*")) assert.True(t, gitConfigContains("key-x = *")) - assert.NoError(t, configSetNonExist("test.key-x", "*")) - assert.NoError(t, configUnsetAll("test.key-x", "*")) + assert.NoError(t, configSetNonExist(ctx, "test.key-x", "*")) + assert.NoError(t, configUnsetAll(ctx, "test.key-x", "*")) assert.False(t, gitConfigContains("key-x = *")) } @@ -60,7 +61,7 @@ func TestSyncConfig(t *testing.T) { }() setting.GitConfig.Options["sync-test.cfg-key-a"] = "CfgValA" - assert.NoError(t, syncGitConfig()) + assert.NoError(t, syncGitConfig(t.Context())) assert.True(t, gitConfigContains("[sync-test]")) assert.True(t, gitConfigContains("cfg-key-a = CfgValA")) } diff --git a/modules/git/git.go b/modules/git/git.go index a2ffd6d2898..0a2e87a2eae 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -34,8 +34,7 @@ type Features struct { } var ( - GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization - DefaultContext context.Context // the default context to run git commands in, must be initialized by git.InitXxx + GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization defaultFeatures *Features ) @@ -53,7 +52,7 @@ func DefaultFeatures() *Features { if !setting.IsProd || setting.IsInTesting { log.Warn("git.DefaultFeatures is called before git.InitXxx, initializing with default values") } - if err := InitSimple(context.Background()); err != nil { + if err := InitSimple(); err != nil { log.Fatal("git.InitSimple failed: %v", err) } } @@ -61,7 +60,7 @@ func DefaultFeatures() *Features { } func loadGitVersionFeatures() (*Features, error) { - stdout, _, runErr := NewCommand("version").RunStdString(DefaultContext, nil) + stdout, _, runErr := NewCommand("version").RunStdString(context.Background(), nil) if runErr != nil { return nil, runErr } @@ -158,18 +157,15 @@ func HomeDir() string { // InitSimple initializes git module with a very simple step, no config changes, no global command arguments. // This method doesn't change anything to filesystem. At the moment, it is only used by some Gitea sub-commands. -func InitSimple(ctx context.Context) error { +func InitSimple() error { if setting.Git.HomePath == "" { return errors.New("unable to init Git's HomeDir, incorrect initialization of the setting and git modules") } - if DefaultContext != nil && (!setting.IsProd || setting.IsInTesting) { + if defaultFeatures != nil && (!setting.IsProd || setting.IsInTesting) { log.Warn("git module has been initialized already, duplicate init may work but it's better to fix it") } - DefaultContext = ctx - globalCommandArgs = nil - if setting.Git.Timeout.Default > 0 { defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second } @@ -196,27 +192,16 @@ func InitSimple(ctx context.Context) error { // InitFull initializes git module with version check and change global variables, sync gitconfig. // It should only be called once at the beginning of the program initialization (TestMain/GlobalInitInstalled) as this code makes unsynchronized changes to variables. -func InitFull(ctx context.Context) (err error) { - if err = InitSimple(ctx); err != nil { +func InitFull() (err error) { + if err = InitSimple(); err != nil { return err } - // Since git wire protocol has been released from git v2.18 - if setting.Git.EnableAutoGitWireProtocol && DefaultFeatures().CheckVersionAtLeast("2.18") { - globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2") - } - - // Explicitly disable credential helper, otherwise Git credentials might leak - if DefaultFeatures().CheckVersionAtLeast("2.9") { - globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=") - } - if setting.LFS.StartServer { if !DefaultFeatures().CheckVersionAtLeast("2.1.2") { 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=") } - return syncGitConfig() + return syncGitConfig(context.Background()) } diff --git a/modules/git/git_test.go b/modules/git/git_test.go index 58ba01cabcb..7a8ca74b015 100644 --- a/modules/git/git_test.go +++ b/modules/git/git_test.go @@ -4,7 +4,6 @@ package git import ( - "context" "fmt" "os" "testing" @@ -25,7 +24,7 @@ func testRun(m *testing.M) error { setting.Git.HomePath = gitHomePath - if err = InitFull(context.Background()); err != nil { + if err = InitFull(); err != nil { return fmt.Errorf("failed to call Init: %w", err) } diff --git a/modules/git/grep_test.go b/modules/git/grep_test.go index 0dce464b7c7..b87ac4bea73 100644 --- a/modules/git/grep_test.go +++ b/modules/git/grep_test.go @@ -11,7 +11,7 @@ import ( ) func TestGrepSearch(t *testing.T) { - repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "language_stats_repo")) + repo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "language_stats_repo")) assert.NoError(t, err) defer repo.Close() diff --git a/modules/git/languagestats/main_test.go b/modules/git/languagestats/main_test.go index 707d268c818..b8f9ded005a 100644 --- a/modules/git/languagestats/main_test.go +++ b/modules/git/languagestats/main_test.go @@ -4,7 +4,6 @@ package languagestats import ( - "context" "fmt" "os" "testing" @@ -22,7 +21,7 @@ func testRun(m *testing.M) error { defer util.RemoveAll(gitHomePath) setting.Git.HomePath = gitHomePath - if err = git.InitFull(context.Background()); err != nil { + if err = git.InitFull(); err != nil { return fmt.Errorf("failed to call Init: %w", err) } diff --git a/modules/git/notes_test.go b/modules/git/notes_test.go index ca05a9e5259..7db2dbc0b9e 100644 --- a/modules/git/notes_test.go +++ b/modules/git/notes_test.go @@ -12,7 +12,7 @@ import ( func TestGetNotes(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -25,7 +25,7 @@ func TestGetNotes(t *testing.T) { func TestGetNestedNotes(t *testing.T) { repoPath := filepath.Join(testReposDir, "repo3_notes") - repo, err := openRepositoryWithDefaultContext(repoPath) + repo, err := OpenRepository(t.Context(), repoPath) assert.NoError(t, err) defer repo.Close() @@ -40,7 +40,7 @@ func TestGetNestedNotes(t *testing.T) { func TestGetNonExistentNotes(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() diff --git a/modules/git/repo.go b/modules/git/repo.go index f1f6902773a..e9405f1b9f4 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -121,17 +121,12 @@ type CloneRepoOptions struct { // Clone clones original repository to target path. func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error { - return CloneWithArgs(ctx, globalCommandArgs, from, to, opts) -} - -// CloneWithArgs original repository to target path. -func CloneWithArgs(ctx context.Context, args TrustedCmdArgs, from, to string, opts CloneRepoOptions) (err error) { toDir := path.Dir(to) - if err = os.MkdirAll(toDir, os.ModePerm); err != nil { + if err := os.MkdirAll(toDir, os.ModePerm); err != nil { return err } - cmd := NewCommandNoGlobals(args...).AddArguments("clone") + cmd := NewCommand().AddArguments("clone") if opts.SkipTLSVerify { cmd.AddArguments("-c", "http.sslVerify=false") } diff --git a/modules/git/repo_base_gogit.go b/modules/git/repo_base_gogit.go index 293aca159c9..e0d0b45372b 100644 --- a/modules/git/repo_base_gogit.go +++ b/modules/git/repo_base_gogit.go @@ -39,11 +39,6 @@ type Repository struct { objectFormat ObjectFormat } -// openRepositoryWithDefaultContext opens the repository at the given path with DefaultContext. -func openRepositoryWithDefaultContext(repoPath string) (*Repository, error) { - return OpenRepository(DefaultContext, repoPath) -} - // OpenRepository opens the repository at the given path within the context.Context func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) { repoPath, err := filepath.Abs(repoPath) diff --git a/modules/git/repo_base_nogogit.go b/modules/git/repo_base_nogogit.go index 6f9bfd4b434..4091e708465 100644 --- a/modules/git/repo_base_nogogit.go +++ b/modules/git/repo_base_nogogit.go @@ -37,11 +37,6 @@ type Repository struct { objectFormat ObjectFormat } -// openRepositoryWithDefaultContext opens the repository at the given path with DefaultContext. -func openRepositoryWithDefaultContext(repoPath string) (*Repository, error) { - return OpenRepository(DefaultContext, repoPath) -} - // OpenRepository opens the repository at the given path with the provided context. func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) { repoPath, err := filepath.Abs(repoPath) diff --git a/modules/git/repo_blob_test.go b/modules/git/repo_blob_test.go index 8a5f5fcd5b0..f07b31d236f 100644 --- a/modules/git/repo_blob_test.go +++ b/modules/git/repo_blob_test.go @@ -14,7 +14,7 @@ import ( func TestRepository_GetBlob_Found(t *testing.T) { repoPath := filepath.Join(testReposDir, "repo1_bare") - r, err := openRepositoryWithDefaultContext(repoPath) + r, err := OpenRepository(t.Context(), repoPath) assert.NoError(t, err) defer r.Close() @@ -42,7 +42,7 @@ func TestRepository_GetBlob_Found(t *testing.T) { func TestRepository_GetBlob_NotExist(t *testing.T) { repoPath := filepath.Join(testReposDir, "repo1_bare") - r, err := openRepositoryWithDefaultContext(repoPath) + r, err := OpenRepository(t.Context(), repoPath) assert.NoError(t, err) defer r.Close() @@ -56,7 +56,7 @@ func TestRepository_GetBlob_NotExist(t *testing.T) { func TestRepository_GetBlob_NoId(t *testing.T) { repoPath := filepath.Join(testReposDir, "repo1_bare") - r, err := openRepositoryWithDefaultContext(repoPath) + r, err := OpenRepository(t.Context(), repoPath) assert.NoError(t, err) defer r.Close() diff --git a/modules/git/repo_branch_test.go b/modules/git/repo_branch_test.go index 8e8ea16fcd9..5d586954db7 100644 --- a/modules/git/repo_branch_test.go +++ b/modules/git/repo_branch_test.go @@ -13,7 +13,7 @@ import ( func TestRepository_GetBranches(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -41,7 +41,7 @@ func TestRepository_GetBranches(t *testing.T) { func BenchmarkRepository_GetBranches(b *testing.B) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(b.Context(), bareRepo1Path) if err != nil { b.Fatal(err) } @@ -57,7 +57,7 @@ func BenchmarkRepository_GetBranches(b *testing.B) { func TestGetRefsBySha(t *testing.T) { bareRepo5Path := filepath.Join(testReposDir, "repo5_pulls") - bareRepo5, err := OpenRepository(DefaultContext, bareRepo5Path) + bareRepo5, err := OpenRepository(t.Context(), bareRepo5Path) if err != nil { t.Fatal(err) } @@ -84,7 +84,7 @@ func TestGetRefsBySha(t *testing.T) { func BenchmarkGetRefsBySha(b *testing.B) { bareRepo5Path := filepath.Join(testReposDir, "repo5_pulls") - bareRepo5, err := OpenRepository(DefaultContext, bareRepo5Path) + bareRepo5, err := OpenRepository(b.Context(), bareRepo5Path) if err != nil { b.Fatal(err) } @@ -97,7 +97,7 @@ func BenchmarkGetRefsBySha(b *testing.B) { } func TestRepository_IsObjectExist(t *testing.T) { - repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare")) + repo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "repo1_bare")) require.NoError(t, err) defer repo.Close() @@ -149,7 +149,7 @@ func TestRepository_IsObjectExist(t *testing.T) { } func TestRepository_IsReferenceExist(t *testing.T) { - repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare")) + repo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "repo1_bare")) require.NoError(t, err) defer repo.Close() diff --git a/modules/git/repo_commit_test.go b/modules/git/repo_commit_test.go index e9f469accdf..3f7883ab14d 100644 --- a/modules/git/repo_commit_test.go +++ b/modules/git/repo_commit_test.go @@ -17,7 +17,7 @@ import ( func TestRepository_GetCommitBranches(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -44,7 +44,7 @@ func TestRepository_GetCommitBranches(t *testing.T) { func TestGetTagCommitWithSignature(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -59,7 +59,7 @@ func TestGetTagCommitWithSignature(t *testing.T) { func TestGetCommitWithBadCommitID(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -71,7 +71,7 @@ func TestGetCommitWithBadCommitID(t *testing.T) { func TestIsCommitInBranch(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -86,7 +86,7 @@ func TestIsCommitInBranch(t *testing.T) { func TestRepository_CommitsBetweenIDs(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo4_commitsbetween") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -108,7 +108,7 @@ func TestRepository_CommitsBetweenIDs(t *testing.T) { func TestGetRefCommitID(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -135,7 +135,7 @@ func TestCommitsByFileAndRange(t *testing.T) { defer test.MockVariableValue(&setting.Git.CommitsRangeSize, 2)() bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) require.NoError(t, err) defer bareRepo1.Close() diff --git a/modules/git/repo_compare_test.go b/modules/git/repo_compare_test.go index 25ee4c51985..35636fae1a7 100644 --- a/modules/git/repo_compare_test.go +++ b/modules/git/repo_compare_test.go @@ -20,7 +20,7 @@ func TestGetFormatPatch(t *testing.T) { return } - repo, err := openRepositoryWithDefaultContext(clonedPath) + repo, err := OpenRepository(t.Context(), clonedPath) if err != nil { assert.NoError(t, err) return @@ -48,7 +48,7 @@ func TestGetFormatPatch(t *testing.T) { func TestReadPatch(t *testing.T) { // Ensure we can read the patch files bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - repo, err := openRepositoryWithDefaultContext(bareRepo1Path) + repo, err := OpenRepository(t.Context(), bareRepo1Path) if err != nil { assert.NoError(t, err) return @@ -86,7 +86,7 @@ func TestReadWritePullHead(t *testing.T) { return } - repo, err := openRepositoryWithDefaultContext(clonedPath) + repo, err := OpenRepository(t.Context(), clonedPath) if err != nil { assert.NoError(t, err) return @@ -122,7 +122,7 @@ func TestReadWritePullHead(t *testing.T) { func TestGetCommitFilesChanged(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - repo, err := openRepositoryWithDefaultContext(bareRepo1Path) + repo, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer repo.Close() diff --git a/modules/git/repo_ref_test.go b/modules/git/repo_ref_test.go index c08ea127603..29c255098f1 100644 --- a/modules/git/repo_ref_test.go +++ b/modules/git/repo_ref_test.go @@ -12,7 +12,7 @@ import ( func TestRepository_GetRefs(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() @@ -37,7 +37,7 @@ func TestRepository_GetRefs(t *testing.T) { func TestRepository_GetRefsFiltered(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() diff --git a/modules/git/repo_stats_test.go b/modules/git/repo_stats_test.go index 85d8807a6e9..538283111bd 100644 --- a/modules/git/repo_stats_test.go +++ b/modules/git/repo_stats_test.go @@ -13,7 +13,7 @@ import ( func TestRepository_GetCodeActivityStats(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) assert.NoError(t, err) defer bareRepo1.Close() diff --git a/modules/git/repo_tag_test.go b/modules/git/repo_tag_test.go index f1f5ff66640..4abb7c4ed9f 100644 --- a/modules/git/repo_tag_test.go +++ b/modules/git/repo_tag_test.go @@ -13,7 +13,7 @@ import ( func TestRepository_GetTags(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - bareRepo1, err := openRepositoryWithDefaultContext(bareRepo1Path) + bareRepo1, err := OpenRepository(t.Context(), bareRepo1Path) if err != nil { assert.NoError(t, err) return @@ -44,7 +44,7 @@ func TestRepository_GetTag(t *testing.T) { return } - bareRepo1, err := openRepositoryWithDefaultContext(clonedPath) + bareRepo1, err := OpenRepository(t.Context(), clonedPath) if err != nil { assert.NoError(t, err) return @@ -136,7 +136,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) { return } - bareRepo1, err := openRepositoryWithDefaultContext(clonedPath) + bareRepo1, err := OpenRepository(t.Context(), clonedPath) if err != nil { assert.NoError(t, err) return diff --git a/modules/git/repo_test.go b/modules/git/repo_test.go index 4638bdac1f8..813844d1ea1 100644 --- a/modules/git/repo_test.go +++ b/modules/git/repo_test.go @@ -12,7 +12,7 @@ import ( func TestGetLatestCommitTime(t *testing.T) { bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") - lct, err := GetLatestCommitTime(DefaultContext, bareRepo1Path) + lct, err := GetLatestCommitTime(t.Context(), bareRepo1Path) assert.NoError(t, err) // Time is Sun Nov 13 16:40:14 2022 +0100 // which is the time of commit @@ -22,7 +22,7 @@ func TestGetLatestCommitTime(t *testing.T) { func TestRepoIsEmpty(t *testing.T) { emptyRepo2Path := filepath.Join(testReposDir, "repo2_empty") - repo, err := openRepositoryWithDefaultContext(emptyRepo2Path) + repo, err := OpenRepository(t.Context(), emptyRepo2Path) assert.NoError(t, err) defer repo.Close() isEmpty, err := repo.IsEmpty() diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go index 7893b95e3a9..55ac0971a5c 100644 --- a/modules/git/submodule_test.go +++ b/modules/git/submodule_test.go @@ -14,7 +14,7 @@ import ( func TestGetTemplateSubmoduleCommits(t *testing.T) { testRepoPath := filepath.Join(testReposDir, "repo4_submodules") - submodules, err := GetTemplateSubmoduleCommits(DefaultContext, testRepoPath) + submodules, err := GetTemplateSubmoduleCommits(t.Context(), testRepoPath) require.NoError(t, err) assert.Len(t, submodules, 2) @@ -39,7 +39,7 @@ func TestAddTemplateSubmoduleIndexes(t *testing.T) { require.NoError(t, err) _, _, err = NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &RunOpts{Dir: tmpDir}) require.NoError(t, err) - submodules, err := GetTemplateSubmoduleCommits(DefaultContext, tmpDir) + submodules, err := GetTemplateSubmoduleCommits(t.Context(), tmpDir) require.NoError(t, err) assert.Len(t, submodules, 1) assert.Equal(t, "new-dir", submodules[0].Path) diff --git a/modules/git/tree_entry_common_test.go b/modules/git/tree_entry_common_test.go index 8b63bbb9931..8e20ee56ff6 100644 --- a/modules/git/tree_entry_common_test.go +++ b/modules/git/tree_entry_common_test.go @@ -13,7 +13,7 @@ import ( ) func TestFollowLink(t *testing.T) { - r, err := openRepositoryWithDefaultContext("tests/repos/repo1_bare") + r, err := OpenRepository(t.Context(), "tests/repos/repo1_bare") require.NoError(t, err) defer r.Close() diff --git a/modules/git/tree_test.go b/modules/git/tree_test.go index cae11c4b1b5..67f95fe7489 100644 --- a/modules/git/tree_test.go +++ b/modules/git/tree_test.go @@ -11,7 +11,7 @@ import ( ) func TestSubTree_Issue29101(t *testing.T) { - repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare")) + repo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "repo1_bare")) assert.NoError(t, err) defer repo.Close() @@ -27,7 +27,7 @@ func TestSubTree_Issue29101(t *testing.T) { } func Test_GetTreePathLatestCommit(t *testing.T) { - repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo6_blame")) + repo, err := OpenRepository(t.Context(), filepath.Join(testReposDir, "repo6_blame")) assert.NoError(t, err) defer repo.Close() diff --git a/modules/graceful/manager.go b/modules/graceful/manager.go index 433e8c4c27c..ee1872b9996 100644 --- a/modules/graceful/manager.go +++ b/modules/graceful/manager.go @@ -47,12 +47,19 @@ var ( // GetManager returns the Manager func GetManager() *Manager { - InitManager(context.Background()) + initManager(context.Background()) return manager } // InitManager creates the graceful manager in the provided context func InitManager(ctx context.Context) { + if manager != nil { + log.Error("graceful.InitManager called more than once") + } + initManager(ctx) // FIXME: this design is not right, it conflicts with the "Background" context used in GetManager +} + +func initManager(ctx context.Context) { initOnce.Do(func() { manager = newGracefulManager(ctx) diff --git a/modules/gtprof/trace_builtin.go b/modules/gtprof/trace_builtin.go index 2590ed3a131..7b4e3b8b4f5 100644 --- a/modules/gtprof/trace_builtin.go +++ b/modules/gtprof/trace_builtin.go @@ -40,7 +40,7 @@ func (t *traceBuiltinSpan) toString(out *strings.Builder, indent int) { if t.ts.endTime.IsZero() { out.WriteString(" duration: (not ended)") } else { - fmt.Fprintf(out, " duration=%.4fs", t.ts.endTime.Sub(t.ts.startTime).Seconds()) + fmt.Fprintf(out, " start=%s duration=%.4fs", t.ts.startTime.Format("2006-01-02 15:04:05"), t.ts.endTime.Sub(t.ts.startTime).Seconds()) } for _, a := range t.ts.attributes { out.WriteString(" ") diff --git a/modules/httplib/url.go b/modules/httplib/url.go index f51506ac3b7..2a1376b8d48 100644 --- a/modules/httplib/url.go +++ b/modules/httplib/url.go @@ -19,7 +19,7 @@ type RequestContextKeyStruct struct{} var RequestContextKey = RequestContextKeyStruct{} func urlIsRelative(s string, u *url.URL) bool { - // Unfortunately browsers consider a redirect Location with preceding "//", "\\", "/\" and "\/" as meaning redirect to "http(s)://REST_OF_PATH" + // Unfortunately, browsers consider a redirect Location with preceding "//", "\\", "/\" and "\/" as meaning redirect to "http(s)://REST_OF_PATH" // Therefore we should ignore these redirect locations to prevent open redirects if len(s) > 1 && (s[0] == '/' || s[0] == '\\') && (s[1] == '/' || s[1] == '\\') { return false diff --git a/modules/indexer/issues/util.go b/modules/indexer/issues/util.go index 19d835a1d80..7647be58e89 100644 --- a/modules/indexer/issues/util.go +++ b/modules/indexer/issues/util.go @@ -97,10 +97,14 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD return nil, false, err } + if err := issue.Repo.LoadOwner(ctx); err != nil { + return nil, false, fmt.Errorf("issue.Repo.LoadOwner: %w", err) + } + return &internal.IndexerData{ ID: issue.ID, RepoID: issue.RepoID, - IsPublic: !issue.Repo.IsPrivate, + IsPublic: !issue.Repo.IsPrivate && issue.Repo.Owner.Visibility.IsPublic(), Title: issue.Title, Content: issue.Content, Comments: comments, diff --git a/modules/indexer/stats/indexer.go b/modules/indexer/stats/indexer.go index 7ec89e2afbd..aaf120c6d0d 100644 --- a/modules/indexer/stats/indexer.go +++ b/modules/indexer/stats/indexer.go @@ -30,7 +30,7 @@ func Init() error { return err } - go populateRepoIndexer(db.DefaultContext) + go populateRepoIndexer(graceful.GetManager().ShutdownContext()) return nil } diff --git a/modules/indexer/stats/indexer_test.go b/modules/indexer/stats/indexer_test.go index d32a8bf1517..088f63234a5 100644 --- a/modules/indexer/stats/indexer_test.go +++ b/modules/indexer/stats/indexer_test.go @@ -7,7 +7,6 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/queue" @@ -33,7 +32,7 @@ func TestRepoStatsIndex(t *testing.T) { err := Init() assert.NoError(t, err) - repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 1) + repo, err := repo_model.GetRepositoryByID(t.Context(), 1) assert.NoError(t, err) err = UpdateRepoIndexer(repo) @@ -41,10 +40,10 @@ func TestRepoStatsIndex(t *testing.T) { assert.NoError(t, queue.GetManager().FlushAll(t.Context(), 5*time.Second)) - status, err := repo_model.GetIndexerStatus(db.DefaultContext, repo, repo_model.RepoIndexerTypeStats) + status, err := repo_model.GetIndexerStatus(t.Context(), repo, repo_model.RepoIndexerTypeStats) assert.NoError(t, err) assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", status.CommitSha) - langs, err := repo_model.GetTopLanguageStats(db.DefaultContext, repo, 5) + langs, err := repo_model.GetTopLanguageStats(t.Context(), repo, 5) assert.NoError(t, err) assert.Empty(t, langs) } diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go index df4bb38ad14..ebda2271f28 100644 --- a/modules/markup/orgmode/orgmode_test.go +++ b/modules/markup/orgmode/orgmode_test.go @@ -97,16 +97,10 @@ func TestRender_Source(t *testing.T) { assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer)) } - test(`#+begin_src go -// HelloWorld prints "Hello World" -func HelloWorld() { - fmt.Println("Hello World") -} + test(`#+begin_src c +int a; #+end_src -`, `
-
// HelloWorld prints "Hello World"
-func HelloWorld() {
-	fmt.Println("Hello World")
-}
+`, `
+
int a;
`) } diff --git a/modules/metrics/collector.go b/modules/metrics/collector.go index 4d2ec287a91..d02e5c11280 100755 --- a/modules/metrics/collector.go +++ b/modules/metrics/collector.go @@ -7,7 +7,7 @@ import ( "runtime" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/setting" "github.com/prometheus/client_golang/prometheus" @@ -233,7 +233,7 @@ func (c Collector) Describe(ch chan<- *prometheus.Desc) { // Collect returns the metrics with values func (c Collector) Collect(ch chan<- prometheus.Metric) { - stats := activities_model.GetStatistic(db.DefaultContext) + stats := activities_model.GetStatistic(graceful.GetManager().ShutdownContext()) ch <- prometheus.MustNewConstMetric( c.Accesses, diff --git a/modules/repository/branch_test.go b/modules/repository/branch_test.go index ead28aa1416..262a35fbf7d 100644 --- a/modules/repository/branch_test.go +++ b/modules/repository/branch_test.go @@ -16,16 +16,16 @@ import ( func TestSyncRepoBranches(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - _, err := db.GetEngine(db.DefaultContext).ID(1).Update(&repo_model.Repository{ObjectFormatName: "bad-fmt"}) - assert.NoError(t, db.TruncateBeans(db.DefaultContext, &git_model.Branch{})) + _, err := db.GetEngine(t.Context()).ID(1).Update(&repo_model.Repository{ObjectFormatName: "bad-fmt"}) + assert.NoError(t, db.TruncateBeans(t.Context(), &git_model.Branch{})) assert.NoError(t, err) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) assert.Equal(t, "bad-fmt", repo.ObjectFormatName) - _, err = SyncRepoBranches(db.DefaultContext, 1, 0) + _, err = SyncRepoBranches(t.Context(), 1, 0) assert.NoError(t, err) repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) assert.Equal(t, "sha1", repo.ObjectFormatName) - branch, err := git_model.GetBranch(db.DefaultContext, 1, "master") + branch, err := git_model.GetBranch(t.Context(), 1, "master") assert.NoError(t, err) assert.Equal(t, "master", branch.Name) } diff --git a/modules/repository/commits_test.go b/modules/repository/commits_test.go index 030cd7714d7..04c07118283 100644 --- a/modules/repository/commits_test.go +++ b/modules/repository/commits_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" @@ -50,7 +49,7 @@ func TestPushCommits_ToAPIPayloadCommits(t *testing.T) { pushCommits.HeadCommit = &PushCommit{Sha1: "69554a6"} repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) - payloadCommits, headCommit, err := pushCommits.ToAPIPayloadCommits(git.DefaultContext, repo) + payloadCommits, headCommit, err := pushCommits.ToAPIPayloadCommits(t.Context(), repo) assert.NoError(t, err) assert.Len(t, payloadCommits, 3) assert.NotNil(t, headCommit) @@ -125,11 +124,11 @@ func TestPushCommits_AvatarLink(t *testing.T) { assert.Equal(t, "/avatars/ab53a2911ddf9b4817ac01ddcd3d975f?size="+strconv.Itoa(28*setting.Avatar.RenderedSizeFactor), - pushCommits.AvatarLink(db.DefaultContext, "user2@example.com")) + pushCommits.AvatarLink(t.Context(), "user2@example.com")) assert.Equal(t, "/assets/img/avatar_default.png", - pushCommits.AvatarLink(db.DefaultContext, "nonexistent@example.com")) + pushCommits.AvatarLink(t.Context(), "nonexistent@example.com")) } func TestCommitToPushCommit(t *testing.T) { diff --git a/modules/repository/create_test.go b/modules/repository/create_test.go index b85a10adad4..68b0f4dea14 100644 --- a/modules/repository/create_test.go +++ b/modules/repository/create_test.go @@ -6,7 +6,6 @@ package repository import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -15,7 +14,7 @@ import ( func TestGetDirectorySize(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 1) + repo, err := repo_model.GetRepositoryByID(t.Context(), 1) assert.NoError(t, err) size, err := getDirectorySize(repo.RepoPath()) assert.NoError(t, err) diff --git a/modules/session/db.go b/modules/session/db.go index 9909f2dc1e9..7b5be1bc705 100644 --- a/modules/session/db.go +++ b/modules/session/db.go @@ -4,11 +4,11 @@ package session import ( + "context" "log" "sync" "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/timeutil" "gitea.com/go-chi/session" @@ -21,6 +21,10 @@ type DBStore struct { data map[any]any } +func dbContext() context.Context { + return context.Background() +} + // NewDBStore creates and returns a DB session store. func NewDBStore(sid string, kv map[any]any) *DBStore { return &DBStore{ @@ -72,7 +76,7 @@ func (s *DBStore) Release() error { return err } - return auth.UpdateSession(db.DefaultContext, s.sid, data) + return auth.UpdateSession(dbContext(), s.sid, data) } // Flush deletes all session data. @@ -98,7 +102,7 @@ func (p *DBProvider) Init(maxLifetime int64, connStr string) error { // Read returns raw session store by session ID. func (p *DBProvider) Read(sid string) (session.RawStore, error) { - s, err := auth.ReadSession(db.DefaultContext, sid) + s, err := auth.ReadSession(dbContext(), sid) if err != nil { return nil, err } @@ -118,7 +122,7 @@ func (p *DBProvider) Read(sid string) (session.RawStore, error) { // Exist returns true if session with given ID exists. func (p *DBProvider) Exist(sid string) bool { - has, err := auth.ExistSession(db.DefaultContext, sid) + has, err := auth.ExistSession(dbContext(), sid) if err != nil { panic("session/DB: error checking existence: " + err.Error()) } @@ -127,12 +131,12 @@ func (p *DBProvider) Exist(sid string) bool { // Destroy deletes a session by session ID. func (p *DBProvider) Destroy(sid string) error { - return auth.DestroySession(db.DefaultContext, sid) + return auth.DestroySession(dbContext(), sid) } // Regenerate regenerates a session store from old session ID to new one. func (p *DBProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) { - s, err := auth.RegenerateSession(db.DefaultContext, oldsid, sid) + s, err := auth.RegenerateSession(dbContext(), oldsid, sid) if err != nil { return nil, err } @@ -152,7 +156,7 @@ func (p *DBProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err err // Count counts and returns number of sessions. func (p *DBProvider) Count() int { - total, err := auth.CountSessions(db.DefaultContext) + total, err := auth.CountSessions(dbContext()) if err != nil { panic("session/DB: error counting records: " + err.Error()) } @@ -161,7 +165,7 @@ func (p *DBProvider) Count() int { // GC calls GC to clean expired sessions. func (p *DBProvider) GC() { - if err := auth.CleanupSessions(db.DefaultContext, p.maxLifetime); err != nil { + if err := auth.CleanupSessions(dbContext(), p.maxLifetime); err != nil { log.Printf("session/DB: error garbage collecting: %v", err) } } diff --git a/modules/setting/actions.go b/modules/setting/actions.go index 8bace1f7504..34346b62cf4 100644 --- a/modules/setting/actions.go +++ b/modules/setting/actions.go @@ -24,7 +24,7 @@ var ( ZombieTaskTimeout time.Duration `ini:"ZOMBIE_TASK_TIMEOUT"` EndlessTaskTimeout time.Duration `ini:"ENDLESS_TASK_TIMEOUT"` AbandonedJobTimeout time.Duration `ini:"ABANDONED_JOB_TIMEOUT"` - SkipWorkflowStrings []string `ìni:"SKIP_WORKFLOW_STRINGS"` + SkipWorkflowStrings []string `ini:"SKIP_WORKFLOW_STRINGS"` }{ Enabled: true, DefaultActionsURL: defaultActionsURLGitHub, diff --git a/modules/setting/config.go b/modules/setting/config.go index 03558574c21..4c5d2df7d8a 100644 --- a/modules/setting/config.go +++ b/modules/setting/config.go @@ -49,6 +49,7 @@ func DefaultOpenWithEditorApps() OpenWithEditorAppsType { type RepositoryStruct struct { OpenWithEditorApps *config.Value[OpenWithEditorAppsType] + GitGuideRemoteName *config.Value[string] } type ConfigStruct struct { @@ -70,6 +71,7 @@ func initDefaultConfig() { }, Repository: &RepositoryStruct{ OpenWithEditorApps: config.ValueJSON[OpenWithEditorAppsType]("repository.open-with.editor-apps"), + GitGuideRemoteName: config.ValueJSON[string]("repository.git-guide-remote-name").WithDefault("origin"), }, } } diff --git a/modules/setting/config/value.go b/modules/setting/config/value.go index f0ec1205447..301c60f5e82 100644 --- a/modules/setting/config/value.go +++ b/modules/setting/config/value.go @@ -46,7 +46,7 @@ func (value *Value[T]) Value(ctx context.Context) (v T) { rev := dg.GetRevision(ctx) - // if the revision in database doesn't change, use the last value + // if the revision in the database doesn't change, use the last value value.mu.RLock() if rev == value.revision { v = value.value @@ -84,6 +84,10 @@ func (value *Value[T]) WithDefault(def T) *Value[T] { return value } +func (value *Value[T]) DefaultValue() T { + return value.def +} + func (value *Value[T]) WithFileConfig(cfgSecKey CfgSecKey) *Value[T] { value.cfgSecKey = cfgSecKey return value diff --git a/modules/setting/cron_test.go b/modules/setting/cron_test.go index 39a228068a0..53996b5de9b 100644 --- a/modules/setting/cron_test.go +++ b/modules/setting/cron_test.go @@ -41,3 +41,56 @@ EXTEND = true assert.Equal(t, "white rabbit", extended.Second) assert.True(t, extended.Extend) } + +// Test_getCronSettings2 tests that getCronSettings can not handle two levels of embedding +func Test_getCronSettings2(t *testing.T) { + type BaseStruct struct { + Enabled bool + RunAtStart bool + Schedule string + } + + type Extended struct { + BaseStruct + Extend bool + } + type Extended2 struct { + Extended + Third string + } + + iniStr := ` +[cron.test] +ENABLED = TRUE +RUN_AT_START = TRUE +SCHEDULE = @every 1h +EXTEND = true +THIRD = white rabbit +` + cfg, err := NewConfigProviderFromData(iniStr) + assert.NoError(t, err) + + extended := &Extended2{ + Extended: Extended{ + BaseStruct: BaseStruct{ + Enabled: false, + RunAtStart: false, + Schedule: "@every 72h", + }, + Extend: false, + }, + Third: "black rabbit", + } + + _, err = getCronSettings(cfg, "test", extended) + assert.NoError(t, err) + + // This confirms the first level of embedding works + assert.Equal(t, "white rabbit", extended.Third) + assert.True(t, extended.Extend) + + // This confirms 2 levels of embedding doesn't work + assert.False(t, extended.Enabled) + assert.False(t, extended.RunAtStart) + assert.Equal(t, "@every 72h", extended.Schedule) +} diff --git a/modules/structs/repo.go b/modules/structs/repo.go index f2e11b15426..404718def0f 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -84,6 +84,7 @@ type Repository struct { Updated time.Time `json:"updated_at"` ArchivedAt time.Time `json:"archived_at"` Permissions *Permission `json:"permissions,omitempty"` + HasCode bool `json:"has_code"` HasIssues bool `json:"has_issues"` InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` @@ -170,6 +171,8 @@ type EditRepoOption struct { Private *bool `json:"private,omitempty"` // either `true` to make this repository a template or `false` to make it a normal repository Template *bool `json:"template,omitempty"` + // either `true` to enable code for this repository or `false` to disable it. + HasCode *bool `json:"has_code,omitempty"` // either `true` to enable issues for this repository or `false` to disable them. HasIssues *bool `json:"has_issues,omitempty"` // set this structure to configure internal issue tracker diff --git a/modules/system/appstate_test.go b/modules/system/appstate_test.go index b5c057cf881..509210127d7 100644 --- a/modules/system/appstate_test.go +++ b/modules/system/appstate_test.go @@ -6,7 +6,6 @@ package system import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" @@ -37,25 +36,25 @@ func TestAppStateDB(t *testing.T) { as := &DBStore{} item1 := new(testItem1) - assert.NoError(t, as.Get(db.DefaultContext, item1)) + assert.NoError(t, as.Get(t.Context(), item1)) assert.Empty(t, item1.Val1) assert.Equal(t, 0, item1.Val2) item1 = new(testItem1) item1.Val1 = "a" item1.Val2 = 2 - assert.NoError(t, as.Set(db.DefaultContext, item1)) + assert.NoError(t, as.Set(t.Context(), item1)) item2 := new(testItem2) item2.K = "V" - assert.NoError(t, as.Set(db.DefaultContext, item2)) + assert.NoError(t, as.Set(t.Context(), item2)) item1 = new(testItem1) - assert.NoError(t, as.Get(db.DefaultContext, item1)) + assert.NoError(t, as.Get(t.Context(), item1)) assert.Equal(t, "a", item1.Val1) assert.Equal(t, 2, item1.Val2) item2 = new(testItem2) - assert.NoError(t, as.Get(db.DefaultContext, item2)) + assert.NoError(t, as.Get(t.Context(), item2)) assert.Equal(t, "V", item2.K) } diff --git a/modules/templates/util_format_test.go b/modules/templates/util_format_test.go index 13a57c24e26..89e42532f96 100644 --- a/modules/templates/util_format_test.go +++ b/modules/templates/util_format_test.go @@ -13,6 +13,6 @@ func TestCountFmt(t *testing.T) { assert.Equal(t, "125", countFmt(125)) assert.Equal(t, "1.3k", countFmt(int64(1317))) assert.Equal(t, "21.3M", countFmt(21317675)) - assert.Equal(t, "45.7G", countFmt(45721317675)) + assert.Equal(t, "45.7G", countFmt(int64(45721317675))) assert.Empty(t, countFmt("test")) } diff --git a/modules/web/handler.go b/modules/web/handler.go index 42a649714d9..843b17e8d1b 100644 --- a/modules/web/handler.go +++ b/modules/web/handler.go @@ -16,7 +16,7 @@ import ( var responseStatusProviders = map[reflect.Type]func(req *http.Request) types.ResponseStatusProvider{} func RegisterResponseStatusProvider[T any](fn func(req *http.Request) types.ResponseStatusProvider) { - responseStatusProviders[reflect.TypeOf((*T)(nil)).Elem()] = fn + responseStatusProviders[reflect.TypeFor[T]()] = fn } // responseWriter is a wrapper of http.ResponseWriter, to check whether the response has been written @@ -48,8 +48,8 @@ func (r *responseWriter) WriteHeader(statusCode int) { } var ( - httpReqType = reflect.TypeOf((*http.Request)(nil)) - respWriterType = reflect.TypeOf((*http.ResponseWriter)(nil)).Elem() + httpReqType = reflect.TypeFor[*http.Request]() + respWriterType = reflect.TypeFor[http.ResponseWriter]() ) // preCheckHandler checks whether the handler is valid, developers could get first-time feedback, all mistakes could be found at startup diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 65ba4e9cd3f..315241a4174 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -120,6 +120,7 @@ error404 = The page you are trying to reach either does not existEnter an absolute path if you run Gitea as a service. reinstall_error = You are trying to install into an existing Gitea database reinstall_confirm_message = Re-installing with an existing Gitea database can cause multiple problems. In most cases, you should use your existing "app.ini" to run Gitea. If you know what you are doing, confirm the following: -reinstall_confirm_check_1 = The data encrypted by the SECRET_KEY in app.ini may be lost: users may not be able to log in with 2FA/OTP and mirrors may not function correctly. By checking this box, you confirm that the current app.ini file contains the correct the SECRET_KEY. +reinstall_confirm_check_1 = The data encrypted by the SECRET_KEY in app.ini may be lost: users may not be able to log in with 2FA/OTP and mirrors may not function correctly. By checking this box, you confirm that the current app.ini file contains the correct SECRET_KEY. reinstall_confirm_check_2 = The repositories and settings may need to be resynchronized. By checking this box, you confirm that you will resynchronize the hooks for the repositories and authorized_keys file manually. You confirm that you will ensure that repository and mirror settings are correct. reinstall_confirm_check_3 = You confirm that you are absolutely sure that this Gitea is running with the correct app.ini location and that you are sure that you have to re-install. You confirm that you acknowledge the above risks. err_empty_db_path = The SQLite3 database path cannot be empty. @@ -1322,6 +1323,7 @@ commit_graph.color = Color commit.contained_in = This commit is contained in: commit.contained_in_default_branch = This commit is part of the default branch commit.load_referencing_branches_and_tags = Load branches and tags referencing this commit +commit.merged_in_pr = This commit was merged in pull request %s. blame = Blame download_file = Download file normal_view = Normal View @@ -2842,6 +2844,11 @@ settings.location = Location settings.permission = Permissions settings.repoadminchangeteam = Repository admin can add and remove access for teams settings.visibility = Visibility +settings.change_visibility = Change Visibility +settings.change_visibility_notices_1 = If the organization is converted to private, the repository stars will be removed and cannot be restored. +settings.change_visibility_notices_2 = Non-members will lose access to the organization’s repositories if visibility is changed to private. +settings.change_visibility_success = The visibility of organization %s has been successfully changed. +settings.visibility_desc = Change who can view the organization and its repositories. settings.visibility.public = Public settings.visibility.limited = Limited (Visible to authenticated users only) settings.visibility.limited_shortname = Limited @@ -3253,7 +3260,7 @@ auths.oauth2_required_claim_name_helper = Set this name to restrict login from t auths.oauth2_required_claim_value = Required Claim Value auths.oauth2_required_claim_value_helper = Set this value to restrict login from this source to users with a claim with this name and value auths.oauth2_group_claim_name = Claim name providing group names for this source. (Optional) -auths.oauth2_full_name_claim_name = Full Name Claim Name. (Optional; if set, the user's full name will always be synchronized with this claim) +auths.oauth2_full_name_claim_name = Full Name Claim Name. (Optional — if set, the user's full name will always be synchronized with this claim) auths.oauth2_ssh_public_key_claim_name = SSH Public Key Claim Name auths.oauth2_admin_group = Group Claim value for administrator users. (Optional — requires claim name above) auths.oauth2_restricted_group = Group Claim value for restricted users. (Optional — requires claim name above) @@ -3418,6 +3425,7 @@ config.picture_service = Picture Service config.disable_gravatar = Disable Gravatar config.enable_federated_avatar = Enable Federated Avatars config.open_with_editor_app_help = The "Open with" editors for the clone menu. If left empty, the default will be used. Expand to see the default. +config.git_guide_remote_name = Repository remote name for git commands in the guide config.git_config = Git Configuration config.git_disable_diff_highlight = Disable Diff Syntax Highlight diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 380f0b3c8d2..c9e074b6594 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -44,6 +44,7 @@ webauthn_use_twofa=Utilisez l'authentification à deux facteurs avec votre tél webauthn_error=Impossible de lire votre clé de sécurité. webauthn_unsupported_browser=Votre navigateur ne prend actuellement pas en charge WebAuthn. webauthn_error_unknown=Une erreur indéterminée s'est produite. Veuillez réessayer. +webauthn_error_insecure=WebAuthn ne prend en charge que les connexions sécurisées. Pour des tests via HTTP, vous pouvez utiliser « localhost » ou « 127.0.0.1 ». webauthn_error_unable_to_process=Le serveur n'a pas pu traiter votre demande. webauthn_error_duplicated=La clé de sécurité n’est pas autorisée pour cette demande. Veuillez vous assurer que la clé n’est pas déjà enregistrée. webauthn_error_empty=Vous devez définir un nom pour cette clé. @@ -187,9 +188,13 @@ code_search_by_git_grep=Les résultats de recherche de code actuels sont fournis package_kind=Chercher des paquets… project_kind=Chercher des projets… branch_kind=Chercher des branches… +tag_kind=Chercher des étiquettes… tag_tooltip=Cherchez des étiquettes correspondantes. Utilisez « % » pour rechercher n’importe quelle suite de nombres. commit_kind=Chercher des révisions… +runner_kind=Chercher des exécuteurs… no_results=Aucun résultat correspondant trouvé. +issue_kind=Recherche de tickets… +pull_kind=Recherche de demandes d’ajouts… keyword_search_unavailable=La recherche par mot clé n’est pas disponible actuellement. Veuillez contacter l’administrateur de votre instance Gitea. [aria] @@ -225,6 +230,8 @@ buttons.enable_monospace_font=Activer la police à chasse fixe buttons.disable_monospace_font=Désactiver la police à chasse fixe [filter] +string.asc=A–Z +string.desc=Z–A [error] occurred=Une erreur s’est produite @@ -245,6 +252,7 @@ license_desc=Venez récupérer documentation avant de modifier les paramètres. require_db_desc=Gitea nécessite MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (avec le protocole MySQL). @@ -261,10 +269,16 @@ path=Emplacement sqlite_helper=Chemin d'accès pour la base de données SQLite3.
Entrer un chemin absolu si vous exécutez Gitea en tant que service. reinstall_error=Vous essayez d'installer dans une base de données Gitea existante reinstall_confirm_message=La réinstallation avec une base de données Gitea existante peut causer plusieurs problèmes. Dans la plupart des cas, vous devriez utiliser votre "app.ini" existant pour exécuter Gitea. Si vous savez ce que vous faites, confirmez ce qui suit : +reinstall_confirm_check_1=Les données chiffrées par la valeur de SECRET_KEY dans app.ini peuvent être invalidés, empêchant les utilisateurs de se connecter via 2FA/OTP et les miroirs de se synchroniser. En cochant cette case, vous confirmez que le fichier app.ini actuel contient la bonne clé SECRET_KEY. +reinstall_confirm_check_2=Les dépôts et les paramètres peuvent avoir besoin d'être re-synchronisés. En cochant cette case, vous confirmez que vous resynchroniserez manuellement les liens des dépôts et du fichier authorized_keys. Vous confirmez que vous allez vous assurer que les paramètres du dépôt et du miroir sont corrects. reinstall_confirm_check_3=Vous confirmez : vous êtes absolument certain que ce Gitea fonctionne avec le bon emplacement de app.ini et vous êtes certain de devoir réinstaller. Vous confirmez également que vous avez pris connaissance des risques exposés ci-dessus. err_empty_db_path=Le chemin de la base de données SQLite3 ne peut être vide. no_admin_and_disable_registration=Vous ne pouvez pas désactiver la création de nouveaux utilisateurs avant d'avoir créé un compte administrateur. err_empty_admin_password=Le mot de passe administrateur ne peut pas être vide. +err_empty_admin_email=Le courriel de l’administrateur ne peut être vide. +err_admin_name_is_reserved=Le nom de l’administrateur est invalide, ce nom d’utilisateur est réservé. +err_admin_name_pattern_not_allowed=Le nom de l’administrateur est invalide, ce nom utilise un motif réservé. +err_admin_name_is_invalid=Le nom de l’administrateur est invalide. general_title=Configuration générale app_name=Titre du site @@ -280,6 +294,7 @@ domain_helper=Domaine ou adresse d'hôte pour le serveur. ssh_port=Port du serveur SSH ssh_port_helper=Port d'écoute du serveur SSH. Laissez le vide pour le désactiver. http_port=Port d'écoute HTTP de Gitea +http_port_helper=Port d’écoute du serveur web Gitea. app_url=URL de base de Gitea app_url_helper=Adresse HTTP(S) de base pour les clones git et les notifications par courriel. log_root_path=Chemin des journaux @@ -343,6 +358,7 @@ no_reply_address=Domaine pour les courriels cachés no_reply_address_helper=Nom de domaine pour les utilisateurs ayant une adresse courriel cachée. Par exemple, l’utilisateur « fred » sera associé à « fred@noreply.example.org » par Git si le domaine est « noreply.example.org ». password_algorithm=Algorithme de hachage du mot de passe invalid_password_algorithm=Algorithme de hachage du mot de passe invalide +password_algorithm_helper=Définissez l’algorithme de hachage du mot de passe. Les algorithmes ont des exigences matérielles et une résistance différentes. L’algorithme argon2 est bien sécurisé mais utilise beaucoup de mémoire et peut être inapproprié pour les systèmes limités en ressources. enable_update_checker=Activer la vérification des mises-à-jour enable_update_checker_helper=Vérifie les mises à jour régulièrement en se connectant à gitea.io. env_config_keys=Configuration de l'environnement @@ -414,6 +430,8 @@ allow_password_change=Demande à l'utilisateur de changer son mot de passe (reco reset_password_mail_sent_prompt=Un mail de confirmation a été envoyé à %s. Veuillez vérifier votre boîte de réception dans les prochaines %s pour terminer la procédure de récupération du compte. active_your_account=Activer votre compte account_activated=Le compte a été activé +prohibit_login=Connexion interdite +prohibit_login_desc=Votre compte n’autorise pas la connexion, veuillez contacter l’administrateur de votre site. resent_limit_prompt=Désolé, vous avez récemment demandé un courriel d’activation. Veuillez réessayer dans 3 minutes. has_unconfirmed_mail=Bonjour %s, votre adresse courriel %s n’a pas été confirmée. Si vous n’avez reçu aucun mail de confirmation ou souhaitez renouveler l’envoi, cliquez sur le bouton ci-dessous. change_unconfirmed_mail_address=Si votre adresse courriel d’inscription est incorrecte, vous pouvez la modifier ici et renvoyer un nouveau courriel de confirmation. @@ -434,6 +452,7 @@ use_scratch_code=Utiliser un code de secours twofa_scratch_used=Vous avez utilisé votre code de secours. Vous avez été redirigé vers cette page de configuration afin de supprimer l'authentification à deux facteurs de votre appareil ou afin de générer un nouveau code de secours. twofa_passcode_incorrect=Votre code d’accès n’est pas correct. Si vous avez égaré votre appareil, utilisez votre code de secours pour vous connecter. twofa_scratch_token_incorrect=Votre code de secours est incorrect. +twofa_required=Vous devez configurer l’authentification à deux facteurs pour avoir accès aux dépôts, ou essayer de vous reconnecter. login_userpass=Connexion login_openid=OpenID oauth_signup_tab=Créer un compte @@ -445,19 +464,24 @@ oauth_signin_submit=Lier un compte oauth.signin.error.general=Une erreur s’est produite lors du traitement de la demande d’autorisation : %s. Si l’erreur persiste, veuillez contacter l’administrateur du site. oauth.signin.error.access_denied=La demande d'autorisation a été refusée. oauth.signin.error.temporarily_unavailable=L'autorisation a échoué car le serveur d'authentification est temporairement indisponible. Veuillez réessayer plus tard. +oauth_callback_unable_auto_reg=L’inscription automatique est activée, mais le fournisseur OAuth2 %[1]s a signalé des champs manquants : %[2]s, impossible de créer un compte automatiquement, veuillez créer ou lier un compte, ou bien contacter l’administrateur du site. openid_connect_submit=Se connecter openid_connect_title=Se connecter à un compte existant openid_connect_desc=L'URI OpenID choisie est inconnue. Associez-le à un nouveau compte ici. openid_register_title=Créer un nouveau compte openid_register_desc=L'URI OpenID choisie est inconnue. Associez-le à un nouveau compte ici. openid_signin_desc=Entrez l'URI de votre OpenID. Par exemple : alice.openid.example.org ou https://openid.example.org/alice. +disable_forgot_password_mail=La récupération du compte est désactivée car aucun courriel n’est configuré. Veuillez contacter l’administrateur de votre site. +disable_forgot_password_mail_admin=La récupération du compte n’est possible que lorsqu’un courriel est configurée. Veuillez ajouter une adresse courriel à votre compte. email_domain_blacklisted=Vous ne pouvez pas vous enregistrer avec votre adresse courriel. authorize_application=Autoriser l'application authorize_redirect_notice=Vous serez redirigé vers %s si vous autorisez cette application. authorize_application_created_by=Cette application a été créée par %s. +authorize_application_description=Si vous accordez l’accès, elle pourra accéder et modifier toutes les informations de votre compte, y compris vos dépôts privés et vos organisations. authorize_application_with_scopes=Avec des contextes : %s authorize_title=Autoriser "%s" à accéder à votre compte ? authorization_failed=L’autorisation a échoué +authorization_failed_desc=L'autorisation a échoué en raison d’une requête invalide. Veuillez contacter le responsable de l'application que vous avez essayé d'autoriser. sspi_auth_failed=Échec de l'authentification SSPI password_pwned=Le mot de passe que vous avez choisi fait partit des mots de passe ayant fuité sur internet. Veuillez réessayer avec un mot de passe différent et considérez remplacer ce mot de passe si vous l’utilisez ailleurs. password_pwned_err=Impossible d'envoyer la demande à HaveIBeenPwned @@ -483,6 +507,7 @@ activate_email.text=Veuillez cliquer sur le lien suivant pour vérifier votre ad register_notify=Bienvenue sur %s register_notify.title=%[1]s, bienvenue à %[2]s register_notify.text_1=Voici votre courriel d’inscription pour %s ! +register_notify.text_2=Vous pouvez maintenant vous connecter avec le nom d’utilisateur : %s. register_notify.text_3=Si ce compte a été créé pour vous, veuillez définir votre mot de passe d'abord. reset_password=Récupérer votre compte @@ -520,6 +545,7 @@ release.download.targz=Code source (TAR.GZ) repo.transfer.subject_to=%s aimerait transférer "%s" à %s repo.transfer.subject_to_you=`%s aimerait vous transférer "%s"` repo.transfer.to_you=vous +repo.transfer.body=Pour l’accepter ou le rejeter, visitez %s ou ignorez-le. repo.collaborator.added.subject=%s vous a ajouté à %s repo.collaborator.added.text=Vous avez été ajouté en tant que collaborateur du dépôt : @@ -571,6 +597,7 @@ url_error=`« %s » n'est pas une URL valide.` include_error=` doit contenir "%s".` glob_pattern_error=` a un motif glob invalide : %s.` regex_pattern_error=` a un motif regex invalide : %s.` +username_error=` ne peut contenir que des caractères alphanumériques « a-z, A-Z, 0-9 », des traits d'union « - », des tirets bas « _ » et des points « . » et ne peux ni commencer, ni finir par des symboles, ni contenir des symboles consécutifs.` invalid_group_team_map_error=` a une cartographie invalide : %s` unknown_error=Erreur inconnue : captcha_incorrect=Le code CAPTCHA est incorrect. @@ -585,14 +612,17 @@ username_has_not_been_changed=Le nom d'utilisateur n'a pas été modifié repo_name_been_taken=Ce nom de dépôt est déjà utilisé. repository_force_private=Force Private est activé : les dépôts privés ne peuvent pas être rendus publics. repository_files_already_exist=Les fichiers existent déjà pour ce dépôt. Contactez l'administrateur système. +repository_files_already_exist.adopt=Des fichiers existent déjà dans ce dépôt et ne peuvent être qu’adoptés. repository_files_already_exist.delete=Des fichiers existent déjà pour ce dépôt. Vous devez les supprimer. repository_files_already_exist.adopt_or_delete=Des fichiers existent déjà dans ce dépôt. Veuillez les adopter ou les supprimer. visit_rate_limit=Le taux d'appel à distance autorisé a été dépassé. +2fa_auth_required=L’accès à distance requiert une authentification à deux facteurs. org_name_been_taken=Ce nom d'organisation est déjà pris. team_name_been_taken=Le nom d'équipe est déjà pris. team_no_units_error=Autoriser l’accès à au moins une section du dépôt. email_been_used=Ce courriel est déjà utilisé. email_invalid=Ce courriel est invalide. +email_domain_is_not_allowed=Le domaine du courriel %s est en conflit avec EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Veuillez vous assurer que votre opération est attendue. openid_been_used=Adresse OpenID "%s" déjà utilisée. username_password_incorrect=Identifiant ou mot de passe invalide. password_complexity=Le mot de passe ne respecte pas les exigences de complexité: @@ -617,8 +647,14 @@ invalid_ssh_key=Impossible de vérifier votre clé SSH : %s invalid_gpg_key=Impossible de vérifier votre clé GPG : %s invalid_ssh_principal=Principal invalide : %s must_use_public_key=La clé que vous avez fournie est une clé privée. Veuillez ne pas divulguer votre clé privée. Utilisez votre clé publique à la place. +unable_verify_ssh_key=Impossible de valider la clé SSH, vérifiez à nouveau s’il y a des erreurs. auth_failed=Échec d'authentification : %v +still_own_repo=Votre compte possède toujours un ou plusieurs dépôts, vous devez d’abord les supprimer ou les transférer. +still_has_org=Votre compte est un membre d’une ou plusieurs organisations, veuillez d’abord les quitter. +still_own_packages=Votre compte possède toujours un ou plusieurs paquets, vous devez d’abord les supprimer ou les transférer. +org_still_own_repo=Cette organisation possède encore un ou plusieurs dépôts. Vous devez d’abord les supprimer ou les transférer. +org_still_own_packages=Cette organisation possède encore un ou plusieurs paquets. Vous devez d’abord les supprimer. target_branch_not_exist=La branche cible n'existe pas. target_ref_not_exist=La réf cible %s n’existe pas @@ -649,9 +685,11 @@ settings=Paramètres utilisateur form.name_reserved=Le nom d’utilisateur "%s" est réservé. form.name_pattern_not_allowed=Le motif « %s » n’est pas autorisé dans un nom de d'utilisateur. +form.name_chars_not_allowed=Le nom d’utilisateur « %s » contient des caractères interdits. block.block=Bloquer block.block.user=Bloquer l’utilisateur +block.block.org=Bloquer l’utilisateur de l’organisation block.block.failure=Impossible de bloquer l’utilisateur : %s block.unblock=Débloquer block.unblock.failure=Impossible de débloquer l’utilisateur : %s @@ -664,6 +702,7 @@ block.info_3=vous envoyer des notifications en vous @mentionnant block.info_4=vous inviter en tant que collaborateur de son(ses) dépôt(s) block.info_5=aimer, bifurquer ou suivre vos dépôts block.info_6=ouvrir ou commenter vos tickets et demandes d’ajouts +block.info_7=réagir à vos commentaires dans les tickets ou les demandes d’ajout block.user_to_block=Utilisateur à bloquer block.note=Note block.note.title=Note facultative : @@ -694,6 +733,7 @@ webauthn=Authentification à deux facteurs (Clés de sécurité) public_profile=Profil public biography_placeholder=Parlez-nous un peu de vous ! (Vous pouvez utiliser Markdown) location_placeholder=Partagez votre position approximative avec d'autres personnes +profile_desc=Contrôlez comment votre profil est affiché aux autres utilisateurs. Votre adresse courriel principale sera utilisée pour les notifications, la récupération de mot de passe et les opérations Git basées sur le Web. password_username_disabled=Vous n’êtes pas autorisé à modifier votre nom d’utilisateur. Veuillez contacter l’administrateur de votre site pour plus de détails. password_full_name_disabled=Vous n’êtes pas autorisé à modifier votre nom complet. Veuillez contacter l’administrateur du site pour plus de détails. full_name=Nom complet @@ -713,6 +753,7 @@ cancel=Annuler language=Langue ui=Thème hidden_comment_types=Catégories de commentaires masqués +hidden_comment_types_description=Cochez les catégories suivantes pour masquer les commentaires correspondants des fils d'activité. Par exemple, « Label » cache les commentaires du genre « Cerise a attribué le label Bug il y a 2 heures. » hidden_comment_types.ref_tooltip=Commentaires où ce ticket a été référencé sur un autre ticket, révision, etc. hidden_comment_types.issue_ref_tooltip=Commentaires où l’utilisateur change la branche/étiquette associée au ticket comment_type_group_reference=Référence @@ -760,14 +801,18 @@ manage_themes=Sélectionner le thème par défaut manage_openid=Gérer les adresses OpenID email_desc=Votre courriel principal sera utilisé pour les notifications, la récupération de mot de passe et, à condition qu’il ne soit pas caché, les opérations Git basées sur le Web. theme_desc=Ce sera votre thème par défaut sur le site. +theme_colorblindness_help=Support du thème daltonien +theme_colorblindness_prompt=Gitea fournit depuis peu des thèmes daltonien basé sur un spectre coloré réduit. Encore en développement, de futures améliorations devraient enrichir les fichiers de thèmes CSS. primary=Principale activated=Activé requires_activation=Nécessite une activation primary_email=Rendre Principal activate_email=Envoyer l’activation activations_pending=Activations en attente +can_not_add_email_activations_pending=Il y a une activation en attente, réessayez dans quelques minutes si vous souhaitez ajouter un nouveau courriel. delete_email=Exclure email_deletion=Supprimer l’adresse courriel +email_deletion_desc=Le courriel et les informations associées seront retirées de votre compte. Les révisions Git effectuées par cette adresse resteront inchangées. Continuer ? email_deletion_success=L’adresse courriel a été supprimée. theme_update_success=Votre thème a été mis à jour. theme_update_error=Le thème sélectionné n'existe pas. @@ -810,6 +855,7 @@ gpg_key_matched_identities_long=Les identités intégrées dans cette clé corre gpg_key_verified=Clé vérifiée gpg_key_verified_long=Cette clé a été vérifiée à l’aide d’un jeton et peut dorénavant être utilisée pour authentifier vos révisions lorsqu’elles contiennent l’un de vos courriels actifs ou des identités associées à cette clé. gpg_key_verify=Vérifier +gpg_invalid_token_signature=La clé GPG, la signature et le jeton fournis ne correspondent pas ou le jeton est périmé. gpg_token_required=Vous devez fournir une signature pour le jeton ci-dessous gpg_token=Jeton gpg_token_help=Vous pouvez générer une signature en utilisant : @@ -819,6 +865,7 @@ verify_gpg_key_success=La clé GPG "%s" a été vérifiée. ssh_key_verified=Clé vérifiée ssh_key_verified_long=La clé a été vérifiée avec un jeton et peut dorénavant être utilisée pour vérifier les révisions comportant l’un des courriels actifs de cet utilisateur. ssh_key_verify=Vérifier +ssh_invalid_token_signature=La clé SSH, la signature ou le jeton fournis ne correspondent pas ou le jeton est périmé. ssh_token_required=Vous devez fournir une signature pour le jeton ci-dessous ssh_token=Jeton ssh_token_help=Vous pouvez générer une signature en utilisant : @@ -839,6 +886,7 @@ gpg_key_deletion=Retirer la clé GPG ssh_principal_deletion=Retirer le Principal de certificat SSH ssh_key_deletion_desc=Le retrait d'une clé SSH révoque son accès à votre compte. Continuer ? gpg_key_deletion_desc=Supprimer une clé GPG discrédite les révisions signées par celle-ci. Continuer ? +ssh_principal_deletion_desc=Le retrait d'un Principal de certificat SSH révoque son accès à votre compte. Poursuivre ? ssh_key_deletion_success=La clé SSH a été retirée. gpg_key_deletion_success=La clé GPG a été retirée. ssh_principal_deletion_success=Le Principal a été retiré. @@ -900,6 +948,7 @@ create_oauth2_application_button=Créer une application create_oauth2_application_success=Vous avez créé une nouvelle application OAuth2 avec succès. update_oauth2_application_success=Vous avez mis à jour l'application OAuth2 avec succès. oauth2_application_name=Nom de l'Application +oauth2_confidential_client=Client confidentiel. Sélectionnez cette option pour les applications qui préservent la confidentialité du secret, telles que les applications web. Ne la sélectionnez pas pour les applications natives, y compris les applications de bureau et les applications mobiles. oauth2_skip_secondary_authorization=Ne plus demander d’autorisation pour les clients publics après la première fois. Introduit un risque de sécurité. oauth2_redirect_uris=URI de redirection. Veuillez utiliser une nouvelle ligne pour chaque URI. save_application=Enregistrer @@ -914,8 +963,10 @@ oauth2_application_remove_description=La suppression d'une application OAuth2 l' oauth2_application_locked=Gitea préinstalle des applications OAuth2 au démarrage si elles sont activées dans la configuration. Pour éviter des comportements inattendus, celles-ci ne peuvent être éditées ni supprimées. Veuillez vous référer à la documentation OAuth2 pour plus d'informations. authorized_oauth2_applications=Applications OAuth2 autorisées +authorized_oauth2_applications_description=Vous avez autorisé l’accès à votre compte personnel Gitea à ces applications tierces. Veuillez révoquer l’accès aux applications dont vous n’avez plus besoin. revoke_key=Révoquer revoke_oauth2_grant=Révoquer l'accès +revoke_oauth2_grant_description=Révoquer l’accès de cette application tierce l’empêchera d’accéder à vos données. Vous êtes sûr ? revoke_oauth2_grant_success=Accès révoqué avec succès. twofa_desc=Pour protéger votre compte contre les vols de mot de passes, vous pouvez utiliser un smartphone ou autres appareils pour recevoir un code temporaire à usage unique (TOTP). @@ -925,6 +976,7 @@ twofa_not_enrolled=Votre compte n'est pas inscrit à l'authentification à deux twofa_disable=Désactiver l'authentification à deux facteurs twofa_scratch_token_regenerate=Régénérer une clé de secours à usage unique twofa_scratch_token_regenerated=Votre clé de secours à usage unique est désormais « %s ». Stockez-la dans un endroit sûr, elle ne sera plus jamais affichée. +twofa_enroll=Activer l‘authentification à deux facteurs twofa_disable_note=Vous pouvez désactiver l'authentification à deux facteurs si nécessaire. twofa_disable_desc=Désactiver l'authentification à deux facteurs rendra votre compte plus vulnérable. Confirmer ? regenerate_scratch_token_desc=Si vous avez égaré votre clé de secours ou avez dû l’utiliser pour vous authentifier, vous pouvez la régénérer. @@ -940,6 +992,7 @@ webauthn_desc=Les clés de sécurité sont des dispositifs matériels contenant webauthn_register_key=Ajouter une clé de sécurité webauthn_nickname=Pseudonyme webauthn_delete_key=Retirer la clé de sécurité +webauthn_delete_key_desc=Si vous retirez une clé de sécurité, vous ne pourrez plus l’utiliser pour vous connecter. Continuer ? webauthn_key_loss_warning=Si vous perdez vos clés de sécurité, vous perdrez l’accès à votre compte. webauthn_alternative_tip=Vous devriez configurer une méthode d’authentification supplémentaire. @@ -968,6 +1021,8 @@ email_notifications.onmention=Seulement sur Mention email_notifications.disable=Ne pas notifier email_notifications.submit=Définir les préférences de courriel email_notifications.andyourown=Inclure vos propres notifications +email_notifications.actions.desc=Notification pour les executions de workflows sur les dépôts configurés avec les Actions Gitea. +email_notifications.actions.failure_only=Ne notifier que pour les exécutions échouées visibility=Visibilité de l'utilisateur visibility.public=Public @@ -1049,10 +1104,12 @@ mirror_sync=synchronisé mirror_sync_on_commit=Synchroniser quand les révisions sont soumis mirror_address=Cloner depuis une URL mirror_address_desc=Insérez tous les identifiants requis dans la section Autorisation. +mirror_address_url_invalid=L’URL fournie est invalide. Vous devez échapper tous les composants de l’URL correctement. mirror_address_protocol_invalid=L'URL fournie est invalide. Seuls les protocoles http(s):// ou git:// peuvent référencer un miroir. mirror_lfs=Stockage de fichiers volumineux (LFS) mirror_lfs_desc=Activer la mise en miroir des données LFS. mirror_lfs_endpoint=Point d'accès LFS +mirror_lfs_endpoint_desc=La synchronisation tentera d’utiliser l’URL de clonage pour identifier le serveur LFS. Vous pouvez spécifier un point d’accès personnalisé si les données LFS du dépôt sont stockées ailleurs. mirror_last_synced=Dernière synchronisation mirror_password_placeholder=(Aucune modification) mirror_password_blank_placeholder=(Non défini) @@ -1065,6 +1122,7 @@ stars=Favoris reactions_more=et %d de plus unit_disabled=L'administrateur du site a désactivé cette section du dépôt. language_other=Autre +adopt_search=Entrez un nom d’utilisateur pour rechercher les dépôts dépossédés… (laissez vide pour tous trouver) adopt_preexisting_label=Adopter les fichiers adopt_preexisting=Adopter les fichiers préexistants adopt_preexisting_content=Créer un dépôt à partir de %s. @@ -1106,6 +1164,8 @@ template.issue_labels=Labels de ticket template.one_item=Vous devez sélectionner au moins un élément du modèle template.invalid=Vous devez sélectionner un modèle de dépôt +archive.title=Ce dépôt est archivé. Vous pouvez voir ses fichiers ou le cloner, mais pas ouvrir de ticket ou de demandes d’ajout, ni soumettre de changements. +archive.title_date=Ce dépôt a été archivé le %s. Vous pouvez voir ses fichiers ou le cloner, mais pas ouvrir de ticket ou de demandes d’ajout, ni soumettre de changements. archive.issue.nocomment=Ce dépôt est archivé. Vous ne pouvez pas commenter de tickets. archive.pull.nocomment=Ce dépôt est archivé. Vous ne pouvez pas commenter de demande d'ajout. @@ -1122,6 +1182,7 @@ migrate_options_lfs=Migrer les fichiers LFS migrate_options_lfs_endpoint.label=Point d'accès LFS migrate_options_lfs_endpoint.description=La migration va tenter d'utiliser votre dépôt Git distant pour déterminer le serveur LFS. Vous pouvez également spécifier un point d'accès personnalisé si les données LFS du dépôt sont stockées ailleurs. migrate_options_lfs_endpoint.description.local=Un chemin de serveur local est également pris en charge. +migrate_options_lfs_endpoint.placeholder=Si laissé vide, le point d’accès sera déterminé à partir de l’URL de clonage. migrate_items=Éléments à migrer migrate_items_wiki=Wiki migrate_items_milestones=Jalons @@ -1133,8 +1194,10 @@ migrate_items_releases=Publications migrate_repo=Migrer le dépôt migrate.clone_address=Migrer/Cloner depuis une URL migrate.clone_address_desc=L'URL HTTP(S) ou Git "clone" d'un dépôt existant +migrate.github_token_desc=Vous pouvez mettre un ou plusieurs jetons séparés par des virgules ici pour rendre la migration plus rapide et contourner la limite de débit de l’API GitHub. ATTENTION : Abuser de cette fonctionnalité peut enfreindre la politique du fournisseur de service et entraîner un blocage de votre compte. migrate.clone_local_path=ou un chemin serveur local migrate.permission_denied=Vous n'êtes pas autorisé à importer des dépôts locaux. +migrate.permission_denied_blocked=Vous ne pouvez pas importer depuis des domaines bannis, veuillez demander à votre administrateur de vérifier les paramètres ALLOWED_DOMAINS, ALLOW_LOCALNETWORKS ou BLOCKED_DOMAINS. migrate.invalid_local_path=Le chemin local n’est pas valide, n’existe pas ou n’est pas un dossier. migrate.invalid_lfs_endpoint=Le point d'accès LFS n'est pas valide. migrate.failed=Echec de migration: %v @@ -1142,6 +1205,7 @@ migrate.migrate_items_options=Un jeton d'accès est requis pour migrer des élé migrated_from=Migré de %[2]s migrated_from_fake=Migré de %[1]s migrate.migrate=Migrer depuis %s +migrate.migrating=Migration de %s… migrate.migrating_failed=La migration de %s a échoué. migrate.migrating_failed.error=Échec de la migration : %s migrate.migrating_failed_no_addr=Échec de la migration. @@ -1190,7 +1254,9 @@ clone_this_repo=Cloner ce dépôt cite_this_repo=Citer ce dépôt create_new_repo_command=Création d'un nouveau dépôt en ligne de commande push_exist_repo=Soumission d'un dépôt existant par ligne de commande +empty_message=Ce dépôt n’a pas de contenu. broken_message=Les données git de ce dépôt ne peuvent pas être lues. Contactez l'administrateur de cette instance ou supprimez ce dépôt. +no_branch=Ce dépôt n’a aucune branche. code=Code code.desc=Accéder au code source, fichiers, révisions et branches. @@ -1207,6 +1273,7 @@ projects=Projets packages=Paquets actions=Actions labels=Labels +org_labels_desc=Les labels d'une organisation peuvent être utilisés avec tous les dépôts de cette organisation. org_labels_desc_manage=gérer milestone=Jalon @@ -1255,6 +1322,7 @@ commit_graph.color=Couleur commit.contained_in=Cette révision appartient à : commit.contained_in_default_branch=Cette révision appartient à la branche par défaut commit.load_referencing_branches_and_tags=Charger les branches et étiquettes référençant cette révision +commit.merged_in_pr=Cette révision a été fusionnée dans la demande d’ajout %s. blame=Annotations download_file=Télécharger le fichier normal_view=Vue normale @@ -1303,13 +1371,17 @@ editor.new_branch_name_desc=Nouveau nom de la branche… editor.cancel=Annuler editor.filename_cannot_be_empty=Le nom de fichier ne peut être vide. editor.filename_is_invalid=Le nom du fichier est invalide : "%s". +editor.commit_email=Courriel de la révision +editor.invalid_commit_email=Le courriel de la révision n’est pas valide. editor.branch_does_not_exist=La branche "%s" n'existe pas dans ce dépôt. editor.branch_already_exists=La branche "%s" existe déjà dans ce dépôt. editor.directory_is_a_file=Le nom de dossier "%s" est déjà utilisé comme nom de fichier dans ce dépôt. +editor.file_is_a_symlink=`« %s » est un lien symbolique. Ce type de fichiers ne peut être modifié dans l’éditeur web.` editor.filename_is_a_directory=« %s » est déjà utilisé comme nom de dossier dans ce dépôt. editor.file_modifying_no_longer_exists=Le fichier en cours d’édition, '%s', n’existe plus dans ce dépôt. editor.file_changed_while_editing=Le contenu du fichier a changé depuis que vous avez commencé à éditer. Cliquez ici pour voir les changements ou soumettez de nouveau pour les écraser. editor.file_already_exists=Un fichier nommé "%s" existe déjà dans ce dépôt. +editor.commit_id_not_matching=L’ID de la révision ne correspond pas à l’ID lorsque vous avez commencé à éditer. Faites une révision dans une branche de correctif puis fusionnez. editor.push_out_of_date=Cet envoi semble être obsolète. editor.commit_empty_file_header=Réviser un fichier vide editor.commit_empty_file_text=Le fichier que vous allez réviser est vide. Continuer ? @@ -1331,8 +1403,11 @@ editor.failed_to_commit=Impossible de réviser les modifications. editor.failed_to_commit_summary=Message d’erreur : editor.fork_create=Bifurquer le Dépôt pour proposer vos modifications +editor.fork_create_description=Vous ne pouvez pas modifier ce dépôt directement. Cependant, vous pouvez bifurquer ce dépôt, et créer une demande d’ajout avec vos contributions. +editor.fork_edit_description=Vous ne pouvez pas modifier ce dépôt directement. Les modifications seront écrites sur une bifurcation %s, vous permettant de faire une demande d’ajout. editor.fork_not_editable=Vous avez bifurqué ce dépôt mais votre copie n’est pas modifiable. editor.fork_failed_to_push_branch=Impossible de pousser la branche %s vers votre dépôt. +editor.fork_branch_exists=La branche « %s » existe déjà dans votre bifurcation, veuillez choisir un nouveau nom. commits.desc=Naviguer dans l'historique des modifications. commits.commits=Révisions @@ -1434,6 +1509,7 @@ issues.new.clear_assignees=Supprimer les affectations issues.new.no_assignees=Sans assignation issues.new.no_reviewers=Sans évaluateur issues.new.blocked_user=Impossible de créer un ticket car vous êtes bloqué par le propriétaire du dépôt. +issues.edit.already_changed=Impossible d’enregistrer le ticket. Il semble que le contenu ait été modifié par un autre utilisateur. Veuillez rafraîchir la page et réessayer pour éviter d’écraser ses modifications. issues.edit.blocked_user=Impossible de modifier ce contenu car vous êtes bloqué par son propriétaire. issues.choose.get_started=Démarrons issues.choose.open_external_link=Ouvrir @@ -1505,6 +1581,7 @@ issues.filter_type.reviewed_by_you=Évaluée par vous issues.filter_sort=Trier issues.filter_sort.latest=Plus récent issues.filter_sort.oldest=Plus ancien +issues.filter_sort.recentupdate=Mis à jour récemment issues.filter_sort.leastupdate=Mis à jour jadis issues.filter_sort.mostcomment=Les plus commentés issues.filter_sort.leastcomment=Les moins commentés @@ -1626,6 +1703,7 @@ issues.lock_no_reason=a verrouillé et limité la conversation aux collaborateur issues.unlock_comment=a déverrouillé cette conversation %s issues.lock_confirm=Verrouiller issues.unlock_confirm=Déverrouiller +issues.lock.notice_1=- Les autres utilisateurs ne peuvent pas ajouter de nouveaux commentaires à ce ticket. issues.lock.notice_2=- Vous et les autres collaborateurs ayant accès à ce dépôt peuvent toujours laisser des commentaires que d’autres peuvent voir. issues.lock.notice_3=- Vous pouvez toujours déverrouiller ce ticket à l'avenir. issues.unlock.notice_1=- Tout le monde sera de nouveau en mesure de commenter ce ticket. @@ -1703,7 +1781,9 @@ issues.dependency.pr_closing_blockedby=La fermeture de cette demande d’ajout e issues.dependency.issue_closing_blockedby=La fermeture de ce ticket est bloquée par les tickets suivants issues.dependency.issue_close_blocks=Ce ticket empêche la clôture des tickets suivants issues.dependency.pr_close_blocks=Cette demande d’ajout empêche la clôture des tickets suivants +issues.dependency.issue_close_blocked=Vous devez fermer tous les tickets qui bloquent celui-ci avant de pouvoir le fermer. issues.dependency.issue_batch_close_blocked=Impossible de fermer tous les tickets que vous avez choisis, car le ticket #%d a toujours des dépendances ouvertes. +issues.dependency.pr_close_blocked=Vous devez fermer tous les tickets qui bloquent cette demande d’ajout avant de pouvoir la fusionner. issues.dependency.blocks_short=Bloque issues.dependency.blocked_by_short=Dépend de issues.dependency.remove_header=Supprimer cette dépendance @@ -1714,11 +1794,13 @@ issues.dependency.add_error_same_issue=Vous ne pouvez pas faire dépendre un tic issues.dependency.add_error_dep_issue_not_exist=Le ticket dépendant n'existe pas. issues.dependency.add_error_dep_not_exist=La dépendance n'existe pas. issues.dependency.add_error_dep_exists=La dépendance existe déjà. +issues.dependency.add_error_cannot_create_circular=Vous ne pouvez pas créer une dépendance si les deux tickets se bloquent mutuellement. issues.dependency.add_error_dep_not_same_repo=Les deux tickets doivent être dans le même dépôt. issues.review.self.approval=Vous ne pouvez approuver vos propres demandes d'ajout. issues.review.self.rejection=Vous ne pouvez demander de changements sur vos propres demandes de changement. issues.review.approve=a approuvé ces modifications %s. issues.review.comment=a évalué %s +issues.review.dismissed=a révoqué l’évaluation de %s %s. issues.review.dismissed_label=Révoquée issues.review.left_comment=à laissé un commentaire issues.review.content.empty=Vous devez laisser un commentaire indiquant le(s) changement(s) demandé(s). @@ -1726,6 +1808,7 @@ issues.review.reject=a requis les changements %s issues.review.wait=a été sollicité pour évaluer cette demande d’ajout %s. issues.review.add_review_request=a demandé à %s une évaluation %s. issues.review.remove_review_request=a retiré la demande d’évaluation pour %s %s. +issues.review.remove_review_request_self=a décliné son invitation à évaluer %s. issues.review.pending=En attente issues.review.pending.tooltip=Ce commentaire n'est pas encore visible par les autres utilisateurs. Pour soumettre vos commentaires en attente, sélectionnez "%s" → "%s/%s/%s" en haut de la page. issues.review.review=Évaluation @@ -1747,6 +1830,7 @@ issues.review.requested=Évaluation en attente issues.review.rejected=Changements demandées issues.review.stale=Modifiée depuis la dernière approbation issues.review.unofficial=Approbation non comptabilisée +issues.assignee.error=Tous les assignés n’ont pas été ajoutés en raison d’une erreur inattendue. issues.reference_issue.body=Corps issues.content_history.deleted=a supprimé issues.content_history.edited=a édité @@ -1763,6 +1847,7 @@ pulls.desc=Active les demandes d’ajouts et l’évaluation du code. pulls.new=Nouvelle demande d'ajout pulls.new.blocked_user=Impossible de créer une demande d’ajout car vous êtes bloqué par le propriétaire du dépôt. pulls.new.must_collaborator=Vous devez être un collaborateur pour créer une demande d’ajout. +pulls.edit.already_changed=Impossible d’enregistrer la demande d’ajout. Il semble que le contenu ait été modifié par un autre utilisateur. Veuillez rafraîchir la page et réessayer afin d’éviter d’écraser leurs modifications. pulls.view=Voir la demande d'ajout pulls.compare_changes=Nouvelle demande d’ajout pulls.allow_edits_from_maintainers=Autoriser les modifications des mainteneurs @@ -1783,9 +1868,11 @@ pulls.show_all_commits=Afficher toutes les révisions pulls.show_changes_since_your_last_review=Affiche les modifications depuis votre dernière évaluation. pulls.showing_only_single_commit=Affiche uniquement les changements de la révision %[1]s pulls.showing_specified_commit_range=Affichage des changements filtré entre %[1]s..%[2]s +pulls.select_commit_hold_shift_for_range=Maintenir Maj et cliquer sur des révisions pour sélectionner un ensemble de révisions. pulls.review_only_possible_for_full_diff=Une évaluation n'est possible que lorsque vous affichez le différentiel complet. pulls.filter_changes_by_commit=Filtrer par révision pulls.nothing_to_compare=Ces branches sont identiques. Il n’y a pas besoin de créer une demande d'ajout. +pulls.nothing_to_compare_have_tag=Les branches/étiquettes sélectionnées sont équivalentes. pulls.nothing_to_compare_and_allow_empty_pr=Ces branches sont égales. Cette demande d'ajout sera vide. pulls.has_pull_request='Il existe déjà une demande d'ajout entre ces deux branches : %[2]s#%[3]d' pulls.create=Créer une demande d'ajout @@ -1810,6 +1897,7 @@ pulls.add_prefix=Ajouter le préfixe %s pulls.remove_prefix=Enlever le préfixe %s pulls.data_broken=Cette demande d’ajout est impossible par manque d'informations de bifurcation. pulls.files_conflicted=Cette demande d'ajout contient des modifications en conflit avec la branche ciblée. +pulls.is_checking=Recherche de conflits de fusion… pulls.is_ancestor=Cette branche est déjà présente dans la branche ciblée. Il n'y a rien à fusionner. pulls.is_empty=Les changements sur cette branche sont déjà sur la branche cible. Cette révision sera vide. pulls.required_status_check_failed=Certains contrôles requis n'ont pas réussi. @@ -1833,12 +1921,16 @@ pulls.reject_count_1=%d changement requis pulls.reject_count_n=%d changements requis pulls.waiting_count_1=%d évaluation en attente pulls.waiting_count_n=%d évaluations en attente +pulls.wrong_commit_id=l’ID de la révision doit être une ID de révision sur la branche cible pulls.no_merge_desc=Cette demande d’ajout ne peut être fusionnée car toutes les options de fusion du dépôt sont désactivées. pulls.no_merge_helper=Activez des options de fusion dans les paramètres du dépôt ou fusionnez la demande manuellement. pulls.no_merge_wip=Cette demande d’ajout ne peut pas être fusionnée car elle est marquée en chantier. +pulls.no_merge_not_ready=Cette demande d’ajout n’est pas prête à être fusionnée, vérifiez les évaluations et le contrôle qualité. pulls.no_merge_access=Vous n'êtes pas autorisé⋅e à fusionner cette demande d'ajout. pulls.merge_pull_request=Créer une révision de fusion +pulls.rebase_merge_pull_request=Rebaser puis rattraper +pulls.rebase_merge_commit_pull_request=Rebaser puis créer une révision de fusion pulls.squash_merge_pull_request=Créer une révision de concaténation pulls.fast_forward_only_merge_pull_request=Avance rapide uniquement pulls.merge_manually=Fusionner manuellement @@ -1846,10 +1938,17 @@ pulls.merge_commit_id=L'ID de la révision de fusion pulls.require_signed_wont_sign=La branche nécessite des révisions signées mais cette fusion ne sera pas signée pulls.invalid_merge_option=Vous ne pouvez pas utiliser cette option de fusion pour cette demande. +pulls.merge_conflict=Échec de la fusion : il y a eu un conflit lors de la fusion. Conseil : Essayez une stratégie différente. pulls.merge_conflict_summary=Message d'erreur +pulls.rebase_conflict=Échec de la fusion : il y a eu un conflit lors du rebasage de la révision %[1]s. Conseil : Essayez une stratégie différente. pulls.rebase_conflict_summary=Message d'erreur +pulls.unrelated_histories=Échec de la fusion : La tête de fusion et la base ne partagent pas d’historique commun. Conseil : Essayez une stratégie différente. +pulls.merge_out_of_date=Échec de la fusion : La base a été mise à jour pendant la fusion. Conseil : Réessayez. +pulls.head_out_of_date=Échec de la fusion : L’en-tête a été mis à jour pendant la fusion. Conseil : réessayez. +pulls.has_merged=Échec : La demande d’ajout est déjà fusionnée, vous ne pouvez plus la fusionner, ni modifier sa branche cible. pulls.push_rejected=Échec de la fusion : la soumission a été rejetée. Revoyez les déclencheurs Git pour ce dépôt. pulls.push_rejected_summary=Message de rejet complet +pulls.push_rejected_no_message=Échec de la fusion : la soumission a été rejetée sans raison. Contrôler les déclencheurs Git pour ce dépôt. pulls.open_unmerged_pull_exists=`Vous ne pouvez pas rouvrir ceci car la demande d’ajout #%d, en attente, a des propriétés identiques.` pulls.status_checking=Certains contrôles sont en attente pulls.status_checks_success=Tous les contrôles ont réussi @@ -1875,6 +1974,7 @@ pulls.cmd_instruction_merge_title=Fusionner pulls.cmd_instruction_merge_desc=Fusionner les modifications et mettre à jour sur Gitea. pulls.cmd_instruction_merge_warning=Attention : cette opération ne peut pas fusionner la demande d’ajout car la « détection automatique de fusion manuelle » n’a pas été activée pulls.clear_merge_message=Effacer le message de fusion +pulls.clear_merge_message_hint=Effacer le message de fusion ne supprimera que le message de la révision, mais pas les pieds de révision générés tels que "Co-Authored-By:". pulls.auto_merge_button_when_succeed=(Lorsque les vérifications ont réussi) pulls.auto_merge_when_succeed=Fusionner automatiquement si toutes les vérifications passent. @@ -1935,10 +2035,12 @@ milestones.filter_sort.most_issues=Le plus de tickets milestones.filter_sort.least_issues=Le moins de tickets signing.will_sign=Cette révision sera signée avec la clé « %s ». +signing.wont_sign.error=Impossible de vérifier la signature de la révision. signing.wont_sign.nokey=Aucune clé n’est disponible pour signer cette révision. signing.wont_sign.never=Les révisions ne sont jamais signées. signing.wont_sign.always=Les révisions sont toujours signées. signing.wont_sign.pubkey=La révision ne sera pas signée car vous votre compte ne possède pas de clé publique. +signing.wont_sign.twofa=Vous devez activer l’authentification à deux facteurs pour signer vos révisions. signing.wont_sign.parentsigned=Cette révision ne sera pas signée car son parent n’est pas signée. signing.wont_sign.basesigned=La fusion ne sera pas signée car la première révision n’est pas signée. signing.wont_sign.headsigned=La fusion ne sera pas signée car la dernière révision n’est pas signée. @@ -2052,11 +2154,13 @@ contributors.contribution_type.additions=Ajouts contributors.contribution_type.deletions=Suppressions settings=Paramètres +settings.desc=Les paramètres sont l’endroit où gérer les options du dépôt. settings.options=Dépôt settings.public_access=Accès public settings.public_access_desc=Configurer les permissions des visiteurs publics remplaçant les valeurs par défaut de ce dépôt. settings.public_access.docs.not_set=Non défini : ne donne aucune permission supplémentaire. Les règles du dépôt et les permissions des utilisateurs font foi. settings.public_access.docs.anonymous_read=Lecture anonyme : les utilisateurs qui ne sont pas connectés peuvent consulter la ressource. +settings.public_access.docs.everyone_read=Consultation collective : tous les utilisateurs connectés peuvent consulter la ressource. Mettre les tickets et demandes d’ajouts en accès public signifie que les utilisateurs connectés peuvent en créer. settings.public_access.docs.everyone_write=Participation collective : tous les utilisateurs connectés ont la permission d’écrire sur la ressource. Seule le Wiki supporte cette autorisation. settings.collaboration=Collaborateurs settings.collaboration.admin=Administrateur @@ -2074,6 +2178,7 @@ settings.mirror_settings.docs.disabled_pull_mirror.instructions=Configurez votre settings.mirror_settings.docs.disabled_push_mirror.instructions=Configurez votre projet pour synchroniser automatiquement les révisions, étiquettes et branches d'un autre dépôt. settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=Pour l’instant, cela ne peut être fait que dans le menu « Nouvelle migration ». Pour plus d’informations, veuillez consulter : settings.mirror_settings.docs.disabled_push_mirror.info=Les miroirs push ont été désactivés par l’administrateur de votre site. +settings.mirror_settings.docs.no_new_mirrors=Votre dépôt se synchronise avec un dépôt distant. Vous ne pouvez pas créer de nouveaux miroirs pour le moment. settings.mirror_settings.docs.can_still_use=Bien que vous ne puissiez pas modifier les miroirs ou en créer de nouveaux, vous pouvez toujours utiliser le(s) miroir(s) existant(s). settings.mirror_settings.docs.pull_mirror_instructions=Pour configurer un miroir pull, veuillez consulter : settings.mirror_settings.docs.more_information_if_disabled=Vous pouvez en savoir plus sur les miroirs push et pull ici : @@ -2148,6 +2253,7 @@ settings.admin_indexer_commit_sha=Dernier SHA indexé settings.admin_indexer_unindexed=Non indexé settings.reindex_button=Ajouter à queue de réindexation settings.reindex_requested=Réindexation demandée +settings.admin_enable_close_issues_via_commit_in_any_branch=Fermer un ticket via une révision faite sur une branche non par défaut settings.danger_zone=Zone de danger settings.new_owner_has_same_repo=Le nouveau propriétaire a déjà un dépôt nommé ainsi. settings.convert=Convertir en dépôt standard @@ -2169,6 +2275,7 @@ settings.transfer_abort_invalid=Vous ne pouvez pas annuler un transfert de dép settings.transfer_abort_success=Le transfert du dépôt vers %s a bien été stoppé. settings.transfer_desc=Transférer ce dépôt à un autre utilisateur ou une organisation dont vous possédez des droits d'administrateur. settings.transfer_form_title=Entrez le nom du dépôt pour confirmer : +settings.transfer_in_progress=Il y a actuellement un transfert en cours. Veuillez l’annuler si vous souhaitez transférer ce dépôt à un autre utilisateur. settings.transfer_notices_1=- Vous perdrez l'accès à ce dépôt si vous le transférez à un autre utilisateur. settings.transfer_notices_2=- Vous conserverez l'accès à ce dépôt si vous le transférez à une organisation dont vous êtes (co-)propriétaire. settings.transfer_notices_3=- Si le dépôt est privé et est transféré à un utilisateur individuel, cette action s'assure que l'utilisateur a au moins la permission de lire (et modifie les permissions si nécessaire). @@ -2183,9 +2290,13 @@ settings.trust_model.default=Par défaut settings.trust_model.default.desc=Utiliser le niveau de confiance configuré par défaut pour cette instance Gitea. settings.trust_model.collaborator=Collaborateur settings.trust_model.collaborator.long=Collaborateur : ne se fier qu'aux signatures des collaborateurs du dépôt +settings.trust_model.collaborator.desc=La signature d’une révision est dite « fiable » si elle correspond à un collaborateur du dépôt, indépendamment de son auteur. À défaut, si elle correspond à l’auteur de la révision, elle sera « dilettante », et « discordante » sinon. settings.trust_model.committer=Auteur +settings.trust_model.committer.long=Auteur : ne se fier qu’aux signatures des auteurs des révisions (mimique GitHub en forçant Gitea à co-signer ses révisions). +settings.trust_model.committer.desc=La signature d’une révision est dite « fiable » si elle corresponds à son auteur, autrement elle est « discordante ». Pour les révisions déléguées à Gitea, elles seront signées par Gitea et l’auteur original sera crédité "Co-authored-by:" et "Co-committed-by:" en pied de révision. Pour cela, la clé configurée par défaut de Gitea doit correspondre à celle d’un utilisateur. settings.trust_model.collaboratorcommitter=Collaborateur et Auteur settings.trust_model.collaboratorcommitter.long=Collaborateur et Auteur : ne se fier qu'aux signatures des auteurs collaborant au dépôt +settings.trust_model.collaboratorcommitter.desc=La signature d’une révision est dite « fiable » si elle correponds à l’auteur collaborant au dépôt. Elle est « dilettante » si elle ne correponds qu’à l'auteur, et autrement « discordante ». Pour les révisions déléguées à Gitea, elles seront signées par Gitea et l’auteur original sera crédité "Co-authored-by:" et "Co-committed-by:" en pied de révision. Pour cela, la clé configurée par défaut de Gitea doit correspondre à celle d’un utilisateur. settings.wiki_delete=Supprimer les données du Wiki settings.wiki_delete_desc=Supprimer les données du wiki d'un dépôt est permanent. Cette action est irréversible. settings.wiki_delete_notices_1=- Ceci supprimera de manière permanente et désactivera le wiki de dépôt pour %s. @@ -2194,6 +2305,7 @@ settings.wiki_deletion_success=Les données du wiki de ce dépôt ont été effa settings.delete=Supprimer ce dépôt settings.delete_desc=Supprimer un dépôt est permanent et irréversible. settings.delete_notices_1=- Cette opération est irréversible. +settings.delete_notices_2=- Cette opération supprimera définitivement le dépôt %s, y compris le code, les tickets, les commentaires, les données de wiki et les accès des collaborateurs. settings.delete_notices_fork_1=- Les bifurcations de ce dépôt deviendront indépendants après suppression. settings.deletion_success=Le dépôt a été supprimé. settings.update_settings_success=Les options du dépôt ont été mises à jour. @@ -2215,6 +2327,8 @@ settings.team_not_in_organization=L'équipe n'est pas dans la même organisation settings.teams=Équipes settings.add_team=Ajouter une équipe settings.add_team_duplicate=L'équipe a déjà le dépôt +settings.add_team_success=L’équipe a maintenant accès au dépôt. +settings.change_team_permission_tip=Les permissions d’équipes sont à définir sur la page de configuration des équipes, et non celle des dépôts. settings.delete_team_tip=Cette équipe a accès à tous les dépôts et ne peut pas être supprimée settings.remove_team_success=L'accès de l'équipe au dépôt a été supprimé. settings.add_webhook=Ajouter un Webhook @@ -2430,6 +2544,7 @@ settings.block_on_official_review_requests_desc=La fusion ne sera pas possible t settings.block_outdated_branch=Bloquer la fusion si la demande d'ajout est obsolète settings.block_outdated_branch_desc=La fusion ne sera pas possible lorsque la branche principale est derrière la branche de base. settings.block_admin_merge_override=Les administrateurs doivent respecter les règles de protection des branches +settings.block_admin_merge_override_desc=Les administrateurs doivent respecter les règles de protection des branches et ne peuvent pas les contourner. settings.default_branch_desc=Sélectionnez une branche par défaut pour les demandes de fusion et les révisions : settings.merge_style_desc=Styles de fusion settings.default_merge_style_desc=Méthode de fusion par défaut @@ -2456,7 +2571,10 @@ settings.matrix.homeserver_url=URL du serveur d'accueil settings.matrix.room_id=ID de la salle settings.matrix.message_type=Type de message settings.visibility.private.button=Rendre privé +settings.visibility.private.text=Rendre le dépôt privé rendra non seulement le dépôt visible uniquement aux membres autorisés, mais peut également rompre la relation entre lui et ses bifurcations, observateurs, et favoris. settings.visibility.private.bullet_title=Changer la visibilité en privé : +settings.visibility.private.bullet_one=Rendra le dépôt visible uniquement aux membres autorisés. +settings.visibility.private.bullet_two=Peut supprimer la relation avec ses bifurcations, ses observateurs et ses favoris. settings.visibility.public.button=Rendre public settings.visibility.public.text=Rendre le dépôt public rendra le dépôt visible à tout le monde. settings.visibility.public.bullet_title=Changer la visibilité en public va : @@ -2475,6 +2593,7 @@ settings.archive.tagsettings_unavailable=Le paramétrage des étiquettes n'est p settings.archive.mirrors_unavailable=Les miroirs ne sont pas disponibles lorsque le dépôt est archivé. settings.unarchive.button=Réhabiliter settings.unarchive.header=Réhabiliter ce dépôt +settings.unarchive.text=Réhabiliter un dépôt dégèle les actions de révisions et de soumissions, la gestion des tickets et des demandes d’ajouts. settings.unarchive.success=Le dépôt a bien été réhabilité. settings.unarchive.error=Une erreur est survenue en essayant deréhabiliter ce dépôt. Voir le journal pour plus de détails. settings.update_avatar_success=L'avatar du dépôt a été mis à jour. @@ -2492,9 +2611,11 @@ settings.lfs_invalid_locking_path=Chemin invalide : %s settings.lfs_invalid_lock_directory=Impossible de verrouiller le répertoire : %s settings.lfs_lock_already_exists=Verrou déjà existant : %s settings.lfs_lock=Verrou +settings.lfs_lock_path=Chemin de fichier à verrouiller… settings.lfs_locks_no_locks=Pas de verrous settings.lfs_lock_file_no_exist=Le fichier verrouillé n'existe pas dans la branche par défaut settings.lfs_force_unlock=Forcer le déverrouillage +settings.lfs_pointers.found=%d pointeur(s) trouvés : %d associés, %d non associés (%d manquant dans le magasin) settings.lfs_pointers.sha=SHA du Blob settings.lfs_pointers.oid=OID settings.lfs_pointers.inRepo=Dans le dépôt @@ -2652,6 +2773,7 @@ branch.new_branch_from=`Créer une nouvelle branche à partir de "%s"` branch.renamed=La branche %s à été renommée en %s. branch.rename_default_or_protected_branch_error=Seuls les administrateurs peuvent renommer les branches par défaut ou protégées. branch.rename_protected_branch_failed=Cette branche est protégée par des règles de protection basées sur des globs. +branch.commits_divergence_from=Divergence de révisions : %[1]d en retard et %[2]d en avance sur %[3]s branch.commits_no_divergence=Identique à la branche %[1]s tag.create_tag=Créer l'étiquette %s @@ -2676,6 +2798,7 @@ error.csv.invalid_field_count=Impossible de visualiser ce fichier car il contien error.broken_git_hook=Les crochets Git de ce dépôt semblent cassés. Veuillez suivre la documentation pour les corriger, puis pousser des révisions pour actualiser le statut. [graphs] +component_loading=Chargement de %s… component_loading_failed=Impossible de charger %s. component_loading_info=Ça prend son temps… component_failed_to_load=Une erreur inattendue s’est produite. @@ -2706,6 +2829,7 @@ team_permission_desc=Autorisation team_unit_desc=Permettre l’accès aux Sections du dépôt team_unit_disabled=(Désactivé) +form.name_been_taken=Le nom d’organisation « %s » a déjà été utilisé. form.name_reserved=Le nom d'organisation "%s" est réservé. form.name_pattern_not_allowed=Le motif « %s » n'est pas autorisé dans un nom d'organisation. form.create_org_not_allowed=Vous n'êtes pas autorisé à créer une organisation. @@ -2713,6 +2837,7 @@ form.create_org_not_allowed=Vous n'êtes pas autorisé à créer une organisatio settings=Paramètres settings.options=Organisation settings.full_name=Nom Complet +settings.email=Courriel de contact settings.website=Site Web settings.location=Localisation settings.permission=Autorisations @@ -2729,7 +2854,10 @@ settings.update_setting_success=Les paramètres de l'organisation ont été mis settings.rename=Renommer l’organisation settings.rename_desc=Changer le nom de l’organisation changera également l’URL de votre organisation et libèrera l’ancien nom. +settings.rename_success=L’organisation %[1]s a bien été renommé en %[2]s. +settings.rename_no_change=Le nom de l’organisation n’a pas été modifié. settings.rename_new_org_name=Nouveau nom d’organisation +settings.rename_failed=Le renommage de l’organisation a échoué en raison d’une erreur interne. settings.rename_notices_1=Cette opération ne peut pas être annulée. settings.rename_notices_2=L’ancien nom redirigera jusqu'à ce qu'il soit réclamé. @@ -2738,10 +2866,12 @@ settings.delete=Supprimer l'organisation settings.delete_account=Supprimer cette organisation settings.delete_prompt=Cette organisation sera supprimée définitivement. Cette action est IRRÉVERSIBLE ! settings.name_confirm=Entrez le nom de l’organisation pour confirmer : -settings.delete_notices_1=Cette opération ne peut pas être annulée. +settings.delete_notices_1=Cette opération ne peut pas être annulée. +settings.delete_notices_2=Cette opération supprimera définitivement tous les dépôts de %s, y compris le code, les tickets, les commentaires, les données de wiki et les accès des collaborateurs. settings.delete_notices_3=Cette opération supprimera définitivement tous les paquets de %s. settings.delete_notices_4=Cette opération supprimera définitivement tous les projets de %s. settings.confirm_delete_account=Confirmer la suppression +settings.delete_failed=La suppression de l’organisation a échoué en raison d’une erreur interne. settings.delete_successful=L’organisation %s a été supprimée avec succès. settings.hooks_desc=Vous pouvez ajouter des webhooks qui seront activés pour tous les dépôts de cette organisation. @@ -2798,6 +2928,7 @@ teams.remove_all_repos_title=Supprimer tous les dépôts de l'équipe teams.remove_all_repos_desc=Ceci supprimera tous les dépôts de l'équipe. teams.add_all_repos_title=Ajouter tous les dépôts teams.add_all_repos_desc=Ceci ajoutera tous les dépôts de l'organisation à l'équipe. +teams.add_nonexistent_repo=Le dépôt que vous essayez d’ajouter n’existe pas, veuillez le créer d’abord. teams.add_duplicate_users=L’utilisateur est déjà un membre de l’équipe. teams.repos.none=Aucun dépôt n'est accessible par cette équipe. teams.members.none=Aucun membre dans cette équipe. @@ -2838,6 +2969,7 @@ repositories=Dépôts hooks=Déclencheurs web integrations=Intégrations authentication=Sources d'authentification +emails=Courriels de l’utilisateur config=Configuration config_summary=Résumé config_settings=Paramètres @@ -2869,8 +3001,11 @@ dashboard.cron.cancelled=Tâche récurrente %[1]s annulée : %[3]s dashboard.cron.error=Erreur dans la tâche récurrente %s : %[3]s dashboard.cron.finished=Tâche récurrente %[1]s terminée dashboard.delete_inactive_accounts=Supprimer tous les comptes non actifs +dashboard.delete_inactive_accounts.started=Début de la suppression de tous les comptes inactifs. dashboard.delete_repo_archives=Supprimer toutes les archives des dépôts (ZIP, TAR.GZ, etc..) +dashboard.delete_repo_archives.started=Début de la suppression de toutes les archives de dépôts. dashboard.delete_missing_repos=Supprimer tous les dépôts dont les fichiers Git sont manquants +dashboard.delete_missing_repos.started=Début de la suppression de tous les dépôts dépourvus de Git. dashboard.delete_generated_repository_avatars=Supprimer les avatars de dépôt générés dashboard.sync_repo_branches=Synchroniser les branches manquantes depuis Git vers la base de donnée. dashboard.sync_repo_tags=Synchroniser les étiquettes git depuis les dépôts vers la base de données @@ -2878,9 +3013,17 @@ dashboard.update_mirrors=Actualiser les miroirs dashboard.repo_health_check=Vérifier l'état de santé de tous les dépôts dashboard.check_repo_stats=Voir les statistiques de tous les dépôts dashboard.archive_cleanup=Supprimer les archives des vieux dépôts +dashboard.deleted_branches_cleanup=Nettoyer les branches supprimées dashboard.update_migration_poster_id=Actualiser les ID des affiches de migration +dashboard.git_gc_repos=Exécuter le ramasse-miette des dépôts +dashboard.resync_all_sshkeys=Mettre à jour le fichier « ssh/authorized_keys » avec les clés SSH Gitea. +dashboard.resync_all_sshprincipals=Mettre à jour le fichier « .ssh/authorized_principals » avec les principaux de Gitea SSH. +dashboard.resync_all_hooks=Re-synchroniser les déclencheurs Git pre-receive, update et post-receive de tous les dépôts. dashboard.reinit_missing_repos=Réinitialiser tous les dépôts Git manquants pour lesquels un enregistrement existe dashboard.sync_external_users=Synchroniser les données de l’utilisateur externe +dashboard.cleanup_hook_task_table=Nettoyer la table hook_task +dashboard.cleanup_packages=Nettoyer des paquets expirés +dashboard.cleanup_actions=Nettoyer les reliquats des actions obsolètes dashboard.server_uptime=Uptime du serveur dashboard.current_goroutine=Goroutines actuelles dashboard.current_memory_usage=Utilisation Mémoire actuelle @@ -2911,8 +3054,10 @@ dashboard.total_gc_pause=Pause GC dashboard.last_gc_pause=Dernière Pause GC dashboard.gc_times=Nombres de GC dashboard.delete_old_actions=Supprimer toutes les anciennes activités de la base de données +dashboard.delete_old_actions.started=Début de la suppression des plus vielles activités de la base de données. dashboard.update_checker=Vérificateur de mise à jour dashboard.delete_old_system_notices=Supprimer toutes les anciennes observations de la base de données +dashboard.gc_lfs=Purger les métaobjets LFS dashboard.stop_zombie_tasks=Arrêter les tâches zombies dashboard.stop_endless_tasks=Arrêter les tâches interminables dashboard.cancel_abandoned_jobs=Annuler les travaux abandonnés @@ -2936,6 +3081,7 @@ users.2fa=2FA users.repos=Dépôts users.created=Créés users.last_login=Dernière connexion +users.never_login=Jamais connecté users.send_register_notify=Envoyer une notification d'inscription users.new_success=Le compte "%s" a bien été créé. users.edit=Éditer @@ -2962,6 +3108,7 @@ users.still_own_repo=Cet utilisateur possède un ou plusieurs dépôts. Veuillez users.still_has_org=Cet utilisateur est membre d'une organisation. Veuillez le retirer de toutes les organisations dont il est membre au préalable. users.purge=Purger l'utilisateur users.purge_help=Éradique l’utilisateur et tous ses dépôts, organisations, commentaires et paquets. +users.still_own_packages=Cet utilisateur possède encore un ou plusieurs paquets. Supprimez d’abord ces paquets. users.deletion_success=Le compte a été supprimé. users.reset_2fa=Réinitialiser l'authentification à deux facteurs users.list_status_filter.menu_text=Filtrer @@ -2981,7 +3128,11 @@ users.details=Informations de l’utilisateur emails.email_manage_panel=Gestion des courriels des utilisateurs emails.primary=Principale emails.activated=Activée -emails.filter_sort.name=Nom d'utilisateur +emails.filter_sort.email=Courriel +emails.filter_sort.email_reverse=Courriel (inversé) +emails.filter_sort.name=Nom d’utilisateur +emails.filter_sort.name_reverse=Nom d’utilisateur (inversé) +emails.updated=Courriel mis à jour emails.not_updated=Impossible de mettre à jour le courriel demandé : %v emails.duplicate_active=Ce courriel est déjà attribué à un autre utilisateur. emails.change_email_header=Mettre à jour les propriétés du courriel @@ -2989,6 +3140,7 @@ emails.change_email_text=Êtes-vous sûr de vouloir mettre à jour cette adresse emails.delete=Supprimer le courriel emails.delete_desc=Êtes-vous sûr de vouloir supprimer ce courriel ? emails.deletion_success=L’adresse courriel a été supprimée. +emails.delete_primary_email_error=Vous ne pouvez pas supprimer le courriel principal. orgs.org_manage_panel=Gestion des organisations orgs.name=Nom @@ -3102,20 +3254,29 @@ auths.oauth2_required_claim_name_helper=Définissez ce nom pour restreindre la c auths.oauth2_required_claim_value=Valeur de réclamation requise auths.oauth2_required_claim_value_helper=Restreindre la connexion depuis cette source aux utilisateurs ayant réclamé cette valeur. auths.oauth2_group_claim_name=Réclamer le nom fournissant les noms de groupe pour cette source. (facultatif) +auths.oauth2_full_name_claim_name=Nom complet réclamé. (Optionnel. Si défini, le nom complet de l’utilisateur sera toujours synchronisé avec cette réclamation) auths.oauth2_ssh_public_key_claim_name=Nom réclamé de la clé publique SSH +auths.oauth2_admin_group=Valeur de réclamation de groupe pour les administrateurs. (Optionnel, nécessite un nom de réclamation) +auths.oauth2_restricted_group=Valeur de réclamation de groupe pour les utilisateurs restreints. (Optionnel, nécessite un nom de réclamation) +auths.oauth2_map_group_to_team=Associe les groupes réclamés avec les équipes de l’organisation. (Optionnel, nécessite un nom de réclamation) auths.oauth2_map_group_to_team_removal=Supprimer les utilisateurs des équipes synchronisées si l'utilisateur n'appartient pas au groupe correspondant. auths.enable_auto_register=Connexion Automatique auths.sspi_auto_create_users=Créer automatiquement des utilisateurs +auths.sspi_auto_create_users_helper=Autoriser la méthode d’authentification SSPI à créer automatiquement de nouveaux comptes pour les utilisateurs qui se connectent pour la première fois. auths.sspi_auto_activate_users=Activer automatiquement les utilisateurs auths.sspi_auto_activate_users_helper=Autoriser la méthode d'authentification SSPI à activer automatiquement les nouveaux utilisateurs auths.sspi_strip_domain_names=Supprimer les noms de domaine des utilisateurs +auths.sspi_strip_domain_names_helper=Nettoie les domaines des noms d’utilisateur (ex. : « DOMAINE\utilisateur » et « utilisateur@exemple.org » ne deviendront que « utilisateur »). auths.sspi_separator_replacement=Séparateur à utiliser au lieu de \, / et @ +auths.sspi_separator_replacement_helper=Le caractère à utiliser pour remplacer les séparateurs dans le nom d’utilisateur (ex. : « \ » dans « DOMAINE\utilisateur », « @ » dans « utilisateur@exemple.org »). auths.sspi_default_language=Langue par défaut de l'utilisateur +auths.sspi_default_language_helper=Langue par défaut pour les utilisateurs créés automatiquement par la méthode d’authentification SSPI. Laissez vide si vous préférez que la langue soit déterminée automatiquement. auths.tips=Conseils auths.tips.oauth2.general=Authentification OAuth2 auths.tips.oauth2.general.tip=Lors de l'enregistrement d'une nouvelle authentification OAuth2, l'URL de rappel/redirection doit être : auths.tip.oauth2_provider=Fournisseur OAuth2 auths.tip.bitbucket=Créez un nouveau jeton OAuth sur %s et ajoutez la permission « Compte » → « Lecture ». +auths.tip.nextcloud=Enregistrez un nouveau client OAuth sur votre instance en atteignant le réglage Paramètres → Sécurité → Client OAuth 2.0. auths.tip.dropbox=Créez une nouvelle application sur %s auths.tip.facebook=Enregistrez une nouvelle application sur%s et ajoutez le produit « Facebook Login ». auths.tip.github=Créez une nouvelle application OAuth sur %s @@ -3225,6 +3386,7 @@ config.mailer_sendmail_path=Chemin d’accès à Sendmail config.mailer_sendmail_args=Arguments supplémentaires pour Sendmail config.mailer_sendmail_timeout=Délai d’attente de Sendmail config.mailer_use_dummy=Factice +config.test_email_placeholder=Courriel (ex : test@exemple.com) config.send_test_mail=Envoyer un courriel de test config.send_test_mail_submit=Envoyer config.test_mail_failed=Impossible d’envoyer un courriel de test à « %s » : %v @@ -3298,6 +3460,7 @@ monitor.start=Heure de démarrage monitor.execute_time=Heure d'Éxécution monitor.last_execution_result=Résultat monitor.process.cancel=Annuler le processus +monitor.process.cancel_desc=L’annulation d’un processus peut entraîner une perte de données. monitor.process.children=Enfant monitor.queues=Files d'attente @@ -3312,6 +3475,7 @@ monitor.queue.numberinqueue=Position dans la queue monitor.queue.review_add=Examiner / ajouter des processus monitor.queue.settings.title=Paramètres du réservoir monitor.queue.settings.desc=Les bassins croissent proportionnellement au besoin de leurs exécuteurs. +monitor.queue.settings.maxnumberworkers=Nombre maximal de processus monitor.queue.settings.maxnumberworkers.placeholder=Actuellement %[1]d monitor.queue.settings.maxnumberworkers.error=Le nombre de processus doit être un nombre monitor.queue.settings.submit=Appliquer les paramètres @@ -3337,6 +3501,10 @@ notices.delete_success=Les informations systèmes ont été supprimées. self_check.no_problem_found=Aucun problème trouvé pour l’instant. self_check.startup_warnings=Avertissements au démarrage : self_check.database_collation_mismatch=Exige que la base de données utilise la collation %s. +self_check.database_collation_case_insensitive=La base de données utilise la collation %s, insensible à la casse. Bien que Gitea soit compatible, il peut y avoir quelques rares cas qui ne fonctionnent pas comme prévu. +self_check.database_inconsistent_collation_columns=La base de données utilise la collation %s, mais ces colonnes utilisent des collations différentes. Cela peut causer des problèmes imprévus. +self_check.database_fix_mysql=Pour les utilisateurs de MySQL ou MariaDB, vous pouvez utiliser la commande « gitea doctor convert » dans un terminal ou exécuter une requête du type « ALTER … COLLATE ... » pour résoudre les problèmes de collation. +self_check.database_fix_mssql=Pour les utilisateurs de MSSQL, vous ne pouvez résoudre le problème qu’en exécutant une requête SQL du type « ALTER … COLLATE … ». self_check.location_origin_mismatch=L’URL actuelle (%[1]s) ne correspond pas à l’URL vue par Gitea (%[2]). Si vous utilisez un proxy inverse, assurez-vous que les en-têtes « Host » et « X-Forwarded-Proto » sont correctement définis. [action] @@ -3420,6 +3588,8 @@ error.no_committer_account=Aucun compte lié au courriel de l’auteur error.no_gpg_keys_found=Signature inconnue de Gitea error.not_signed_commit=Révision non signée error.failed_retrieval_gpg_keys=Impossible de récupérer la clé liée au compte de l'auteur +error.probable_bad_signature=AVERTISSEMENT ! Bien qu’il y ait une clé avec cet ID dans la base de données, elle ne vérifie pas cette révision ! Cette révision est SUSPECTE. +error.probable_bad_default_signature=AVERTISSEMENT ! Bien que la clé par défaut ait cet ID, elle ne vérifie pas cette révision ! Cette révision est SUSPECTE. [units] unit=Ressource @@ -3458,6 +3628,7 @@ versions.view_all=Voir tout dependency.id=ID dependency.version=Version search_in_external_registry=Rechercher dans %s +alpine.registry=Configurez ce registre en ajoutant l’URL dans votre fichier /etc/apk/repositories : alpine.registry.key=Téléchargez la clé RSA publique du registre dans le dossier /etc/apk/keys/ pour vérifier la signature de l'index : alpine.registry.info=Choisissez $branch et $repository dans la liste ci-dessous. alpine.install=Pour installer le paquet, exécutez la commande suivante : @@ -3470,13 +3641,18 @@ arch.install=Synchroniser le paquet avec pacman : arch.repository=Informations sur le Dépôt arch.repository.repositories=Dépôts arch.repository.architectures=Architectures +cargo.registry=Configurez ce registre dans le fichier de configuration Cargo (par exemple ~/.cargo/config.toml) : cargo.install=Pour installer le paquet en utilisant Cargo, exécutez la commande suivante : +chef.registry=Configurer ce registre dans votre fichier ~/.chef/config.rb : chef.install=Pour installer le paquet, exécutez la commande suivante : +composer.registry=Configurez ce registre dans votre fichier ~/.composer/config.json : composer.install=Pour installer le paquet en utilisant Composer, exécutez la commande suivante : composer.dependencies=Dépendances composer.dependencies.development=Dépendances de développement conan.details.repository=Dépôt +conan.registry=Configurez ce registre à partir d'un terminal : conan.install=Pour installer le paquet en utilisant Conan, exécutez la commande suivante : +conda.registry=Configurez ce registre en tant que dépôt Conda dans le fichier .condarc : conda.install=Pour installer le paquet en utilisant Conda, exécutez la commande suivante : container.details.type=Type d'image container.details.platform=Plateforme @@ -3488,7 +3664,9 @@ container.layers=Calques d'image container.labels=Labels container.labels.key=Clé container.labels.value=Valeur +cran.registry=Configurez ce registre dans le fichier Rprofile.site : cran.install=Pour installer le paquet, exécutez la commande suivante : +debian.registry=Configurez ce registre à partir d'un terminal : debian.registry.info=Choisissez $distribution et $component dans la liste ci-dessous. debian.install=Pour installer le paquet, exécutez la commande suivante : debian.repository=Infos sur le Dépôt @@ -3497,11 +3675,16 @@ debian.repository.components=Composants debian.repository.architectures=Architectures generic.download=Télécharger le paquet depuis un terminal : go.install=Installer le paquet à partir de la ligne de commande : +helm.registry=Configurer ce registre à partir d'un terminal : helm.install=Pour installer le paquet, exécutez la commande suivante : +maven.registry=Configurez ce registre dans le fichier pom.xml de votre projet : +maven.install=Pour utiliser le paquet, inclure ce qui suit dans le bloc dependencies dans le fichier pom.xml : maven.install2=Exécuter dans un terminal : maven.download=Pour télécharger la dépendance, exécutez dans un terminal : +nuget.registry=Configurer ce registre à partir d'un terminal : nuget.install=Pour installer le paquet en utilisant NuGet, exécutez la commande suivante : nuget.dependency.framework=Cadriciel cible +npm.registry=Configurez ce registre dans le fichier .npmrc de votre projet : npm.install=Pour installer le paquet en utilisant npm, exécutez la commande suivante : npm.install2=ou ajoutez-le au fichier package.json : npm.dependencies=Dépendances @@ -3513,6 +3696,7 @@ npm.details.tag=Balise pub.install=Pour installer le paquet en utilisant Dart, exécutez la commande suivante : pypi.requires=Nécessite Python pypi.install=Pour installer le paquet en utilisant pip, exécutez la commande suivante : +rpm.registry=Configurez ce registre à partir d'un terminal : rpm.distros.redhat=sur les distributions basées sur RedHat rpm.distros.suse=sur les distributions basées sur SUSE rpm.install=Pour installer le paquet, exécutez la commande suivante : @@ -3525,6 +3709,7 @@ rubygems.dependencies.runtime=Dépendances d'exécution rubygems.dependencies.development=Dépendances de développement rubygems.required.ruby=Nécessite Ruby en version rubygems.required.rubygems=Nécessite RubyGem en version +swift.registry=Configurez ce registre à partir d'un terminal : swift.install=Ajoutez le paquet dans votre fichier Package.swift: swift.install2=et exécutez la commande suivante : vagrant.install=Pour ajouter une machine Vagrant, exécutez la commande suivante : @@ -3547,6 +3732,7 @@ owner.settings.cargo.initialize.success=L'index Cargo a été créé avec succè owner.settings.cargo.rebuild=Reconstruire l'index owner.settings.cargo.rebuild.description=La reconstruction peut être utile si l'index n'est pas synchronisé avec les paquets Cargo stockés. owner.settings.cargo.rebuild.error=Impossible de reconstruire l'index Cargo : %v +owner.settings.cargo.rebuild.success=L’index Cargo a été reconstruit avec succès. owner.settings.cleanuprules.title=Gérer les règles de nettoyage owner.settings.cleanuprules.add=Ajouter une règle de nettoyage owner.settings.cleanuprules.edit=Modifier la règle de nettoyage @@ -3634,6 +3820,7 @@ runners.delete_runner=Supprimer cet exécuteur runners.delete_runner_success=Exécuteur supprimé avec succès runners.delete_runner_failed=Impossible de supprimer l'Exécuteur runners.delete_runner_header=Êtes-vous sûr de vouloir supprimer cet exécuteur ? +runners.delete_runner_notice=Si une tâche est en cours sur cet exécuteur, elle sera terminée et marquée comme échouée. Cela risque d’interrompre le flux de travail. runners.none=Aucun exécuteur disponible runners.status.unspecified=Inconnu runners.status.idle=Inactif diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index 313a9ab499c..cb0c2373ede 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -948,6 +948,7 @@ create_oauth2_application_button=Cruthaigh Feidhmchlár create_oauth2_application_success=D'éirigh leat feidhmchlár nua OAuth2 a chruthú. update_oauth2_application_success=D'éirigh leat an feidhmchlár OAuth2 a nuashonrú. oauth2_application_name=Ainm Feidhmchláir +oauth2_confidential_client=Cliant Rúnda. Roghnaigh le haghaidh aipeanna a choinníonn an rún faoi rún, amhail aipeanna gréasáin. Ná roghnaigh le haghaidh aipeanna dúchasacha, lena n-áirítear aipeanna deisce agus soghluaiste. oauth2_skip_secondary_authorization=Scipeáil údarú do chliaint poiblí tar éis rochtain a dheonú D'fhéadfadh sé go mbeadh riosca slándála oauth2_redirect_uris=URIs a atreorú. Úsáid líne nua do gach URI le do thoil. save_application=Sábháil @@ -962,8 +963,10 @@ oauth2_application_remove_description=Cuirfear feidhmchlár OAuth2 a bhaint cosc oauth2_application_locked=Réamhchláraíonn Gitea roinnt feidhmchlár OAuth2 ar thosú má tá sé cumasaithe i gcumraíocht. Chun iompar gan choinne a chosc, ní féidir iad seo a chur in eagar ná a bhaint. Féach do thoil do dhoiciméadú OAuth2 le haghaidh tuilleadh faisnéise. authorized_oauth2_applications=Feidhmchláir Údaraithe OAuth2 +authorized_oauth2_applications_description=Tá rochtain tugtha agat do na feidhmchláir tríú páirtí seo ar do chuntas pearsanta Gitea. Le do thoil, cuir rochtain ar ceal i gcás feidhmchlár nach bhfuil uait a thuilleadh. revoke_key=Cúlghairm revoke_oauth2_grant=Rochtain a chúlghairm +revoke_oauth2_grant_description=Má chúlghairtear rochtain don fheidhmchlár tríú páirtí seo, cuirfidh sé cosc ar an fheidhmchlár seo rochtain a fháil ar do shonraí. An bhfuil tú cinnte? revoke_oauth2_grant_success=Cúlghairtear rochtain go rathúil. twofa_desc=Chun do chuntas a chosaint ar goid pasfhocal, is féidir leat fón cliste nó gléas eile a úsáid chun pasfhocail aon-uaire bunaithe ar am (“TOTP”) a fháil. @@ -973,6 +976,7 @@ twofa_not_enrolled=Níl do chuntas cláraithe faoi láthair i bhfíordheimhniú twofa_disable=Díchumasaigh Fíordheimhniú Dhá-Fachtóir twofa_scratch_token_regenerate=Athghin Eochair Aisghabhála Aonúsáide twofa_scratch_token_regenerated=Is é %s d'eochair aisghabhála aonúsáide anois. Stóráil é in áit shábháilte, mar ní thaispeánfar é arís. +twofa_enroll=Cláraigh i bhFíordheimhniú Dhá-Fachtóir twofa_disable_note=Is féidir leat fíordheimhniú dhá fhachtóir a dhíchumasú más gá. twofa_disable_desc=Má dhíchumasaítear fíordheimhniú dhá fhachtóir beidh do chuntas chomh slán. Lean ar aghaidh? regenerate_scratch_token_desc=Má chuir tú d'eochair aisghabhála míchuir tú nó má d'úsáid tú é cheana féin chun síniú isteach, is féidir leat é a athshocrú anseo. @@ -988,6 +992,7 @@ webauthn_desc=Is feistí crua-earraí iad eochracha slándála ina bhfuil eochra webauthn_register_key=Cuir Eochair Slándála webauthn_nickname=Leasainm webauthn_delete_key=Bain Eochair Slándála +webauthn_delete_key_desc=Mura mbaintear eochair slándála uait, ní féidir leat síniú isteach léi a thuilleadh. Ar mhaith leat leanúint ar aghaidh? webauthn_key_loss_warning=Má chailleann tú d'eochracha slándála, caillfidh tú rochtain ar do chuntas. webauthn_alternative_tip=B'fhéidir gur mhaith leat modh fíordheimhnithe breise a chumrú. @@ -1104,6 +1109,7 @@ mirror_address_protocol_invalid=Tá an URL curtha ar fáil neamhbhailí. Ní fé mirror_lfs=Stóráil Comhad Móra (LFS) mirror_lfs_desc=Gníomhachtaigh scáthú sonraí LFS. mirror_lfs_endpoint=Críochphointe LFS +mirror_lfs_endpoint_desc=Déanfaidh Sync iarracht an URL clónála a úsáid chun an freastalaí LFS a chinneadh. Is féidir leat críochphointe saincheaptha a shonrú freisin má tá sonraí LFS an stórais stóráilte in áit eile. mirror_last_synced=Sincronaithe Deireanach mirror_password_placeholder=(Gan athrú) mirror_password_blank_placeholder=(Neamhshocraithe) @@ -1116,6 +1122,7 @@ stars=Réaltaí reactions_more=agus %d níos mó unit_disabled=Tá an chuid stórais seo díchumasaithe ag riarthóir an láithreáin. language_other=Eile +adopt_search=Cuir isteach ainm úsáideora chun cuardach a dhéanamh ar stórtha neamhuchtaithe… (fág bán chun gach ceann a aimsiú) adopt_preexisting_label=Glacadh le Comhaid adopt_preexisting=Glac le comhaid atá ann cheana adopt_preexisting_content=Cruthaigh stór ó %s @@ -1157,6 +1164,8 @@ template.issue_labels=Lipéid Eisiúna template.one_item=Ní mór mír teimpléad amháin ar a laghad a roghnú template.invalid=Ní mór stór teimpléad a roghnú +archive.title=Tá an stór seo cartlannaithe. Is féidir leat comhaid a fheiceáil agus é a chlónáil. Ní féidir leat saincheisteanna a oscailt ná iarratais a tharraingt ná tiomnú a bhrú. +archive.title_date=Tá an stórlann seo cartlannaithe ar %s. Is féidir leat comhaid a fheiceáil agus é a chlónáil. Ní féidir leat saincheisteanna a oscailt ná iarratais a tharraingt ná tiomnú a bhrú. archive.issue.nocomment=Tá an stóras seo i gcartlann. Ní féidir leat trácht a dhéanamh ar shaincheisteanna. archive.pull.nocomment=Tá an stóras seo i gcartlann. Ní féidir leat trácht a dhéanamh ar iarratais tarraingthe. @@ -1173,6 +1182,7 @@ migrate_options_lfs=Aimirce comhaid LFS migrate_options_lfs_endpoint.label=Críochphointe LFS migrate_options_lfs_endpoint.description=Déanfaidh imirce iarracht do chianda Git a úsáid chun freastalaí LFS a chinneadh. Is féidir leat críochphointe saincheaptha a shonrú freisin má tá na sonraí LFS stórtha stóráilte áit éigin eile. migrate_options_lfs_endpoint.description.local=Tacaítear le cosán freastalaí áitiúil freisin. +migrate_options_lfs_endpoint.placeholder=Mura bhfágtar bán é, díorthófar an críochphointe ón URL clónála. migrate_items=Míreanna Imirce migrate_items_wiki=Wiki migrate_items_milestones=Clocha míle @@ -1184,8 +1194,10 @@ migrate_items_releases=Eisiúintí migrate_repo=Stóras Imirc migrate.clone_address=Aimirce/ Clón Ó URL migrate.clone_address_desc=An URL 'clón' HTTP(S) nó Git de stóras atá ann cheana +migrate.github_token_desc=Is féidir leat comhartha amháin nó níos mó a chur anseo, scartha le camóga, chun an t-aistriú a dhéanamh níos tapúla trí theorainn ráta API GitHub a sheachaint. RABHADH: D’fhéadfadh mí-úsáid a bhaint as an ngné seo sárú a dhéanamh ar pholasaí an tsoláthraí seirbhíse agus d’fhéadfadh sé go gcuirfí bac ar do chuntas(í). migrate.clone_local_path=nó cosán freastalaí áitiúil migrate.permission_denied=Ní cheadaítear duit stórais áitiúla a iompórtáil. +migrate.permission_denied_blocked=Ní féidir leat iompórtáil ó óstaigh neamhcheadaithe. Iarr ar an riarthóir socruithe ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS a sheiceáil. migrate.invalid_local_path=Tá an cosán áitiúil neamhbhailí. Níl sé ann nó ní eolaire é. migrate.invalid_lfs_endpoint=Níl an críochphointe LFS bailí. migrate.failed=Theip ar an imirce:% v @@ -1193,6 +1205,7 @@ migrate.migrate_items_options=Teastaíonn Comhartha Rochtana chun míreanna brei migrated_from=Aistríodh ó %[2]s migrated_from_fake=Aistrithe ó %[1]s migrate.migrate=Aistrigh Ó %s +migrate.migrating=Ag aistriú ó %s… migrate.migrating_failed=Theip ar aistriú ó %s. migrate.migrating_failed.error=Theip ar aistriú: %s migrate.migrating_failed_no_addr=Theip ar an imirce. @@ -1241,6 +1254,7 @@ clone_this_repo=Clóin an stóras seo cite_this_repo=Luaigh an stóras seo create_new_repo_command=Stóras nua a chruthú ar an líne ordaithe push_exist_repo=Stóras atá ann cheana a bhrú ón líne ordaithe +empty_message=Níl aon ábhar sa stórlann seo. broken_message=Ní féidir na sonraí Git atá mar bhunús leis an stóras seo a léamh. Déan teagmháil le riarthóir an chás seo nó scrios an stóras seo. no_branch=Níl aon bhrainse ag an stóras seo. @@ -1259,6 +1273,7 @@ projects=Tionscadail packages=Pacáistí actions=Gníomhartha labels=Lipéid +org_labels_desc=Lipéid ar leibhéal na heagraíochta is féidir a úsáid le gach stórlann faoin eagraíocht seo org_labels_desc_manage=bainistigh milestone=Cloch Mhíle @@ -1307,6 +1322,7 @@ commit_graph.color=Dath commit.contained_in=Tá an tiomantas seo le fáil i: commit.contained_in_default_branch=Tá an tiomantas seo mar chuid den bhrainse réamhshocraithe commit.load_referencing_branches_and_tags=Luchtaigh brainsí agus clibeanna a thagraíonn an tiomantas +commit.merged_in_pr=Cuireadh an tiomantas seo le chéile san iarratas tarraingthe %s. blame=An milleán download_file=Íoslódáil comhad normal_view=Amharc Gnáth @@ -1355,13 +1371,17 @@ editor.new_branch_name_desc=Ainm brainse nua… editor.cancel=Cealaigh editor.filename_cannot_be_empty=Ní féidir ainm an chomhaid a bheith folamh. editor.filename_is_invalid=Tá ainm an chomhaid neamhbhailí: "%s". +editor.commit_email=Seoladh ríomhphoist tiomanta +editor.invalid_commit_email=Tá an seoladh ríomhphoist don tiomnú neamhbhailí. editor.branch_does_not_exist=Níl brainse "%s" ann sa stóras seo. editor.branch_already_exists=Tá brainse "%s" ann cheana féin sa stóras seo. editor.directory_is_a_file=Úsáidtear ainm eolaire "%s" cheana féin mar ainm comhaid sa stóras seo. +editor.file_is_a_symlink=Is nasc siombalach é `"%s". Ní féidir naisc shiombalacha a chur in eagar san eagarthóir gréasáin.` editor.filename_is_a_directory=Úsáidtear ainm comhaid "%s" cheana féin mar ainm eolaire sa stóras seo. editor.file_modifying_no_longer_exists=Níl an comhad atá á mhodhnú, "%s", sa stóras seo a thuilleadh. editor.file_changed_while_editing=Tá athrú tagtha ar ábhar an chomhad ó thosaigh tú ag eagarthóireacht Cliceáil anseo chun iad a fheiceáil nó Athru ithe a Tiomantas arís chun iad a fhorscríobh. editor.file_already_exists=Tá comhad darb ainm "%s" ann cheana féin sa stóras seo. +editor.commit_id_not_matching=Ní hionann an ID Tiomnaithe agus an ID a bhí ann nuair a thosaigh tú ag eagarthóireacht. Cuir isteach i mbrainse paiste é agus ansin cumasc é. editor.push_out_of_date=Is cosúil go bhfuil an brú as dáta. editor.commit_empty_file_header=Tiomantas comhad folamh editor.commit_empty_file_text=Tá an comhad atá tú ar tí tiomantas folamh. Ar aghaidh? @@ -1387,6 +1407,7 @@ editor.fork_create_description=Ní féidir leat an stórlann seo a chur in eagar editor.fork_edit_description=Ní féidir leat an stórlann seo a chur in eagar go díreach. Scríobhfar na hathruithe chuig do fhorc %s, ionas gur féidir leat iarratas tarraingthe a chruthú. editor.fork_not_editable=Tá forc déanta agat ar an stóras seo ach ní féidir do fhorc a chur in eagar. editor.fork_failed_to_push_branch=Theip ar bhrainse %s a bhrú chuig do stóras. +editor.fork_branch_exists=Tá brainse "%s" ann cheana féin i do fhorc. Roghnaigh ainm brainse nua le do thoil. commits.desc=Brabhsáil stair athraithe cód foinse. commits.commits=Tiomáintí @@ -1488,6 +1509,7 @@ issues.new.clear_assignees=Ceannaitheoirí soiléir issues.new.no_assignees=Gan aon Sannaitheoirí issues.new.no_reviewers=Gan Léirmheastóirí issues.new.blocked_user=Ní féidir saincheist a chruthú toisc go bhfuil úinéir an stórais bac ort. +issues.edit.already_changed=Ní féidir athruithe ar an gceist a shábháil. Is cosúil gur athraigh úsáideoir eile an t-ábhar cheana féin. Athnuachan an leathanach agus déan iarracht eagarthóireacht arís le nach scríobhfar a gcuid athruithe thar a chéile. issues.edit.blocked_user=Ní féidir ábhar a chur in eagar toisc go bhfuil an póstaer nó úinéir an stórais bac ort. issues.choose.get_started=Faigh Tosaigh issues.choose.open_external_link=Oscailte @@ -1559,6 +1581,7 @@ issues.filter_type.reviewed_by_you=Athbhreithnithe agat issues.filter_sort=Sórtáil issues.filter_sort.latest=Is nuaí issues.filter_sort.oldest=Is sine +issues.filter_sort.recentupdate=Nuashonraithe le déanaí issues.filter_sort.leastupdate=Is lú a nuashonraíodh le déanaí issues.filter_sort.mostcomment=Is mó a bhfuil tráchtanna air issues.filter_sort.leastcomment=Is lú a bhfuil tráchtanna air @@ -1758,7 +1781,9 @@ issues.dependency.pr_closing_blockedby=Cuireann na saincheisteanna seo a leanas issues.dependency.issue_closing_blockedby=Tá na saincheisteanna seo a leanas bac ar dhúnadh an cheist seo issues.dependency.issue_close_blocks=Cuireann an tsaincheist seo bac ar dhúnadh na saincheisteanna issues.dependency.pr_close_blocks=Cuireann an iarratas tarraingthe seo bac ar dhúnadh na saincheisteanna +issues.dependency.issue_close_blocked=Ní mór duit gach saincheist atá ag cur bac ar an gceist seo a dhúnadh sula bhféadfaidh tú í a dhúnadh. issues.dependency.issue_batch_close_blocked=Ní féidir saincheisteanna a roghnaíonn tú a dhúnadh, toisc go bhfuil spleáchais oscailte fós ag eisiúint #%d +issues.dependency.pr_close_blocked=Ní mór duit gach saincheist atá ag cur bac ar an iarratas tarraingthe seo a dhúnadh sula bhféadfaidh tú é a chumasc. issues.dependency.blocks_short=Bloic issues.dependency.blocked_by_short=Ag brath ar issues.dependency.remove_header=Bain spleáchas @@ -1769,11 +1794,13 @@ issues.dependency.add_error_same_issue=Ní féidir leat ceist a dhéanamh ag bra issues.dependency.add_error_dep_issue_not_exist=Níl saincheist spleách ann. issues.dependency.add_error_dep_not_exist=Ní bhíonn spleáchas ann. issues.dependency.add_error_dep_exists=Tá spleáchas ann cheana féin. +issues.dependency.add_error_cannot_create_circular=Ní féidir leat spleáchas a chruthú le dhá shaincheist a chuireann bac ar a chéile. issues.dependency.add_error_dep_not_same_repo=Caithfidh an dá shaincheist a bheith sa stór céanna. issues.review.self.approval=Ní féidir leat d'iarratas tarraingthe féin a cheadú. issues.review.self.rejection=Ní féidir leat athruithe a iarraidh ar d'iarratas tarraingthe féin. issues.review.approve=ceadaigh na hathruithe seo %s issues.review.comment=athbhreithnithe %s +issues.review.dismissed=léirmheas %s %s curtha ar ceal issues.review.dismissed_label=Dhiúltaigh issues.review.left_comment=d'fhág trácht issues.review.content.empty=Ní mór duit trácht a fhágáil a léiríonn an t-athrú (í) iarrtha. @@ -1781,6 +1808,7 @@ issues.review.reject=athruithe iarrtha %s issues.review.wait=iarradh athbhreithniú %s issues.review.add_review_request=athbhreithniú iarrtha ó %s %s issues.review.remove_review_request=iarratas athbhreithnithe bainte le haghaidh %s %s +issues.review.remove_review_request_self=dhiúltaigh athbhreithniú a dhéanamh ar %s issues.review.pending=Ar feitheamh issues.review.pending.tooltip=Níl an nóta tráchta seo le feiceáil ag úsáideoirí eile faoi láthair. Chun do thuairimí ar feitheamh a chur isteach, roghnaigh "%s" -> "%s/%s/%s" ag barr an leathanaigh. issues.review.review=Léirmheas @@ -1802,6 +1830,7 @@ issues.review.requested=Athbhreithniú ar feitheamh issues.review.rejected=Athruithe iarrtha issues.review.stale=Nuashonraithe ó faomhadh issues.review.unofficial=Ceadú gan áireamh +issues.assignee.error=Níor cuireadh na sannaithe go léir leis, mar gheall ar earráid gan choinne. issues.reference_issue.body=Comhlacht issues.content_history.deleted=scriosta issues.content_history.edited=curtha in eagar @@ -1818,6 +1847,7 @@ pulls.desc=Cumasaigh iarratais tarraingthe agus athbhreithnithe cód. pulls.new=Iarratas Tarraingthe Nua pulls.new.blocked_user=Ní féidir iarratas tarraingthe a chruthú toisc go bhfuil úinéir an stórais bac ort. pulls.new.must_collaborator=Caithfidh tú a bheith ina chomhoibritheoir chun iarratas tarraingthe a chruthú. +pulls.edit.already_changed=Ní féidir athruithe ar an iarratas tarraingthe a shábháil. Is cosúil gur athraigh úsáideoir eile an t-ábhar cheana féin. Athnuachan an leathanach agus déan iarracht eagarthóireacht arís le nach ndéanfar a gcuid athruithe a fhorscríobh. pulls.view=Féach ar Iarratas Tarraing pulls.compare_changes=Iarratas Tarraingthe Nua pulls.allow_edits_from_maintainers=Ceadaigh eagarthóirí ó chothabhálaí @@ -1838,6 +1868,7 @@ pulls.show_all_commits=Taispeáin gach gealltanas pulls.show_changes_since_your_last_review=Taispeáin athruithe ón léirmheas deiridh pulls.showing_only_single_commit=Ag taispeáint athruithe tiomantais %[1]s amháin pulls.showing_specified_commit_range=Ag taispeáint athruithe idir %[1]s..%[2]s +pulls.select_commit_hold_shift_for_range=Roghnaigh tiomantas. Coinnigh síos Shift agus cliceáil chun raon a roghnú. pulls.review_only_possible_for_full_diff=Ní féidir athbhreithniú a dhéanamh ach amháin nuair a bhreathnaítear ar an difríocht iomlán pulls.filter_changes_by_commit=Scagaigh de réir tiomantas pulls.nothing_to_compare=Tá na brainsí seo cothrom. Ní gá iarratas tarraingthe a chruthú. @@ -1866,6 +1897,7 @@ pulls.add_prefix=Cuir réimír %s leis pulls.remove_prefix=Bain an réimír %s pulls.data_broken=Tá an t-iarratas tarraingthe seo briste mar gheall ar fhaisnéis forc a bheith in easnamh. pulls.files_conflicted=Tá athruithe ag an iarratas tarraingthe seo atá contrártha leis an spriocbhrainse. +pulls.is_checking=Ag seiceáil le haghaidh coinbhleachtaí cumaisc… pulls.is_ancestor=Tá an brainse seo san áireamh cheana féin sa spriocbhrainse. Níl aon rud le cumasc. pulls.is_empty=Tá na hathruithe ar an mbrainse seo ar an spriocbhrainse cheana féin. Is tiomantas folamh é seo. pulls.required_status_check_failed=Níor éirigh le roinnt seiceálacha riachtanacha. @@ -1889,12 +1921,16 @@ pulls.reject_count_1=%d iarratas athraithe pulls.reject_count_n=%d iarratas ar athrú pulls.waiting_count_1=%d athbhreithniú feithimh pulls.waiting_count_n=%d athbhreithnithe feithimh +pulls.wrong_commit_id=ní mór don ID tiomantais a bheith ina ID tiomantais ar an mbrainse sprice pulls.no_merge_desc=Ní féidir an t-iarratas tarraingthe seo a chumasc toisc go bhfuil gach rogha cumaisc stór díchumasaithe. pulls.no_merge_helper=Cumasaigh roghanna cumaisc i socruithe an stór nó cumasc an t-iarratas tarraingthe de láimh. pulls.no_merge_wip=Ní féidir an t-iarratas tarraingthe seo a chumasc toisc go bhfuil sé marcáilte mar obair atá ar siúl é. +pulls.no_merge_not_ready=Níl an t-iarratas tarraingthe seo réidh le cumasc. Seiceáil stádas an athbhreithnithe agus na seiceálacha stádais. pulls.no_merge_access=Níl tú údaraithe chun an t-iarratas tarraingthe seo a chumasc. pulls.merge_pull_request=Cruthaigh tiomantas cumaisc +pulls.rebase_merge_pull_request=Athbhunús, ansin luasghéarú ar aghaidh +pulls.rebase_merge_commit_pull_request=Athbhunú, ansin cruthaigh tiomantas cumasc pulls.squash_merge_pull_request=Cruthaigh tiomantas scuaise pulls.fast_forward_only_merge_pull_request=Go tapa ar aghaidh amháin pulls.merge_manually=Cumaisc de láimh @@ -1902,10 +1938,17 @@ pulls.merge_commit_id=ID an tiomantis cumaisc pulls.require_signed_wont_sign=Éilíonn an bhrainse tiomáintí shínithe, ach ní shínífear an cumasc seo pulls.invalid_merge_option=Ní féidir leat an rogha cumaisc seo a úsáid don iarratas tarraingthe seo. +pulls.merge_conflict=Theip ar an gCumasc: Bhí coimhlint ann agus an cumasc á dhéanamh. Leid: Bain triail as straitéis dhifriúil. pulls.merge_conflict_summary=Teachtaireacht Earráide +pulls.rebase_conflict=Theip ar an gCumasc: Bhí coimhlint ann agus an tiomnú á athbhunú: %[1]s. Leid: Bain triail as straitéis dhifriúil. pulls.rebase_conflict_summary=Teachtaireacht Earráide +pulls.unrelated_histories=Theip ar an gCumasc: Níl stair choiteann ag an gceann agus an bonn cumaisc. Leid: Bain triail as straitéis dhifriúil. +pulls.merge_out_of_date=Theip ar an gCumasc: Nuashonraíodh an bonn agus an cumasc á ghiniúint. Leid: Bain triail eile as. +pulls.head_out_of_date=Theip ar an gCumasc: Nuashonraíodh an ceannteideal agus an cumasc á ghiniúint. Leid: Bain triail eile as. +pulls.has_merged=Theip air: Tá an t-iarratas tarraingthe cumasctha. Ní féidir leat cumasc arís ná an brainse sprice a athrú. pulls.push_rejected=Theip ar Brúigh: Diúltaíodh don bhrú. Déan athbhreithniú ar na Git Hooks don stór seo. pulls.push_rejected_summary=Teachtaireacht Diúltaithe Iomlán +pulls.push_rejected_no_message=Theip ar Bhrú: Diúltaíodh don bhrú ach ní raibh aon teachtaireacht iargúlta ann. Athbhreithnigh na Git Hooks don stór seo. pulls.open_unmerged_pull_exists=`Ní féidir leat oibríocht athoscailte a dhéanamh toisc go bhfuil iarratas tarraingthe ar feitheamh (#%d) le hairíonna comhionanna. ` pulls.status_checking=Tá roinnt seiceála ar feitheamh pulls.status_checks_success=D'éirigh le gach seiceáil @@ -1931,6 +1974,7 @@ pulls.cmd_instruction_merge_title=Cumaisc pulls.cmd_instruction_merge_desc=Cumaisc na hathruithe agus nuashonrú ar Gitea. pulls.cmd_instruction_merge_warning=Rabhadh: Ní féidir iarratas tarraingthe cumaisc a dhéanamh leis an oibríocht seo mar nach bhfuil "autodetect manual merge" cumasaithe. pulls.clear_merge_message=Glan an teachtaireacht chumaisc +pulls.clear_merge_message_hint=Má ghlanann tú an teachtaireacht chumasc, ní bhainfear ach ábhar na teachtaireachta tiomantais agus coinneofar leantóirí git ginte amhail "Comhúdaraithe ag…". pulls.auto_merge_button_when_succeed=(Nuair a éiríonn le seiceálacha) pulls.auto_merge_when_succeed=Cumaisc uathoibríoch nuair a éiríonn @@ -1996,6 +2040,7 @@ signing.wont_sign.nokey=Níl aon eochair ar fáil chun an tiomantas seo a shíni signing.wont_sign.never=Ní shínítear tiomáintí riamh. signing.wont_sign.always=Sínítear tiomáintí i gcónaí. signing.wont_sign.pubkey=Ní shíníofar an tiomantas toisc nach bhfuil eochair phoiblí agat a bhaineann le do chuntas. +signing.wont_sign.twofa=Ní mór fíordheimhniú dhá fhachtóir a bheith cumasaithe agat le go síneofar gealltanais. signing.wont_sign.parentsigned=Ní shíníofar an tiomantas toisc nach bhfuil an tiomantas tuismitheora sínithe. signing.wont_sign.basesigned=Ní shínífear an cumasc toisc nach bhfuil an tiomantas bunaithe sínithe. signing.wont_sign.headsigned=Ní shínífear an cumasc toisc nach bhfuil an tiomantas ceann sínithe. @@ -2109,11 +2154,13 @@ contributors.contribution_type.additions=Breiseanna contributors.contribution_type.deletions=Scriosadh settings=Socruithe +settings.desc=Is i socruithe is féidir leat na socruithe don stór a bhainistiú. settings.options=Stóras settings.public_access=Rochtain Phoiblí settings.public_access_desc=Cumraigh ceadanna rochtana an chuairteora phoiblí chun réamhshocruithe an stóras seo a shárú. settings.public_access.docs.not_set=Gan Socrú: níl cead rochtana poiblí breise ar bith. Leanann cead an chuairteora infheictheacht an stór agus ceadanna na mball. settings.public_access.docs.anonymous_read=Léamh gan Ainm: is féidir le húsáideoirí nach bhfuil logáilte isteach rochtain a fháil ar an aonad le cead léite. +settings.public_access.docs.everyone_read=Léigh Gach Duine: is féidir le gach úsáideoir atá logáilte isteach rochtain a fháil ar an aonad le cead léite. Ciallaíonn cead léite na n-aonad saincheiste/iarratais tarraingthe freisin gur féidir le húsáideoirí saincheisteanna/iarratais tarraingthe nua a chruthú. settings.public_access.docs.everyone_write=Scríobh Gach Duine: tá cead scríofa ag gach úsáideoir logáilte isteach don aonad. Ní thacaíonn ach aonad Vicí leis an gcead seo. settings.collaboration=Comhoibritheoirí settings.collaboration.admin=Riarthóir @@ -2131,6 +2178,7 @@ settings.mirror_settings.docs.disabled_pull_mirror.instructions=Socraigh do thio settings.mirror_settings.docs.disabled_push_mirror.instructions=Socraigh do thionscadal chun tiomáintí, clibeanna agus brainsí a tharraingt go huathoibríoch ó stóras eile. settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=Faoi láthair, ní féidir é seo a dhéanamh ach sa roghchlár "Imirce Nua". Le haghaidh tuilleadh eolais, téigh i gcomhairle le do thoil: settings.mirror_settings.docs.disabled_push_mirror.info=Chuir riarthóir do shuíomh faoi dhíchumasú scátháin bhrú. +settings.mirror_settings.docs.no_new_mirrors=Tá do stóras ag scáthánú athruithe chuig nó ó stór eile. Coinnigh i gcuimhne nach féidir leat aon scátháin nua a chruthú faoi láthair. settings.mirror_settings.docs.can_still_use=Cé nach féidir leat scátháin atá ann cheana a mhodhnú nó cinn nua a chruthú, féadfaidh tú do scáthán atá ann cheana a úsáid fós. settings.mirror_settings.docs.pull_mirror_instructions=Chun scáthán tarraingthe a shocrú, téigh i gcomhairle le do thoil: settings.mirror_settings.docs.more_information_if_disabled=Is féidir leat tuilleadh eolais a fháil faoi scátháin bhrú agus tarraingthe anseo: @@ -2205,6 +2253,7 @@ settings.admin_indexer_commit_sha=SHA Innéacsaithe Deiridh settings.admin_indexer_unindexed=Neamh-innéacsaithe settings.reindex_button=Cuir le Scuaine Reindex settings.reindex_requested=Athinnéacsú Iarrtha +settings.admin_enable_close_issues_via_commit_in_any_branch=Dún saincheist trí thiomantas a rinneadh i mbrainse neamhréamhshocraithe settings.danger_zone=Crios Contúirte settings.new_owner_has_same_repo=Tá stóras leis an ainm céanna ag an úinéir nua cheana féin. Roghnaigh ainm eile le do thoil. settings.convert=Tiontaigh go Stóras Rialta @@ -2226,6 +2275,7 @@ settings.transfer_abort_invalid=Ní féidir leat aistriú stóras nach bhfuil an settings.transfer_abort_success=Cuireadh an t-aistriú stóras chuig %s ar ceal go rathúil. settings.transfer_desc=Aistrigh an stóras seo chuig úsáideoir nó chuig eagraíocht a bhfuil cearta riarthóra agat ina leith. settings.transfer_form_title=Cuir isteach ainm an stóras mar dhearbhú: +settings.transfer_in_progress=Tá aistriú ar siúl faoi láthair. Cealaigh é más mian leat an stóras seo a aistriú chuig úsáideoir eile. settings.transfer_notices_1=- Caillfidh tú rochtain ar an stóras má aistríonn tú é chuig úsáideoir aonair. settings.transfer_notices_2=- Coimeádfaidh tú rochtain ar an stóras má aistríonn tú é chuig eagraíocht a bhfuil (comh)úinéir agat. settings.transfer_notices_3=- Má tá an stóras príobháideach agus má aistrítear é chuig úsáideoir aonair, cinnteoidh an gníomh seo go bhfuil ar a laghad cead léite ag an úsáideoir (agus athraíonn sé ceadanna más gá). @@ -2240,9 +2290,13 @@ settings.trust_model.default=Múnla Iontaobhais Réamhshocraithe settings.trust_model.default.desc=Úsáid an tsamhail iontaobhais stórais réamhshocraithe don suiteáil settings.trust_model.collaborator=Comhoibritheoir settings.trust_model.collaborator.long=Comhoibritheoir: Sínithe muinín ag comhoibrithe +settings.trust_model.collaborator.desc=Déanfar sínithe bailí ó chomhoibritheoirí an stórais seo a mharcáil mar "iontaofa", cibé acu a mheaitseálann siad an tiomnóir nó nach meaitseálann. Seachas sin, déanfar sínithe bailí a mharcáil mar "neamhiontaofa" má mheaitseálann an síniú an tiomnóir agus "gan mheaitseáil" mura bhfuil. settings.trust_model.committer=Coimisitheoir +settings.trust_model.committer.long=Tiomnaithe: Sínithe muiníne a mheaitseálann tiomnóirí. Meaitseálann sé seo iompar GitHub agus cuirfidh sé iallach ar thiomnóirí atá sínithe ag Gitea Gitea a bheith mar an tiomnóir. +settings.trust_model.committer.desc=Ní mharcálfar sínithe bailí mar "iontaofa" ach amháin má mheaitseálann siad an tiomnaí, nó marcálfar iad mar "gan mheaitseáil". Cuireann sé seo iallach ar Gitea a bheith ina tiomnaí ar thiomnuithe sínithe, agus an tiomnaí iarbhír marcáilte mar Chomhúdaraithe ag: agus Co-thiomnaithe ag: leantóir sa tiomnú. Caithfidh eochair réamhshocraithe Gitea a bheith ag teacht le húsáideoir sa bhunachar sonraí. settings.trust_model.collaboratorcommitter=Comhoibritheo+Coimiteoir settings.trust_model.collaboratorcommitter.long=Comhoibrí+Coiste: sínithe muiníne ó chomhoibrithe a mheaitseálann an tiomnóir +settings.trust_model.collaboratorcommitter.desc=Marcálfar sínithe bailí ó chomhoibritheoirí an stórais seo mar "iontaofa" má mheaitseálann siad an tiomnaí. Seachas sin, marcálfar sínithe bailí mar "neamhiontaofa" má mheaitseálann an síniú an tiomnaí agus "gan mheaitseáil" murach sin. Cuirfidh sé seo iallach ar Gitea a bheith marcáilte mar an tiomnaí ar thiomnuithe sínithe, agus an tiomnaí iarbhír marcáilte mar Chomhúdaraithe ag: agus Co-Tiomnaithe ag: leantóir sa tiomnú. Ní mór don eochair réamhshocraithe Gitea a bheith ag teacht le húsáideoir sa bhunachar sonraí. settings.wiki_delete=Scrios Sonraí Vicí settings.wiki_delete_desc=Tá sonraí wiki stóras a scriosadh buan agus ní féidir iad a chur ar ais. settings.wiki_delete_notices_1=- Scriosfaidh agus díchumasóidh sé seo an stóras vicí do %s go buan. @@ -2251,6 +2305,7 @@ settings.wiki_deletion_success=Scriosadh sonraí vicí an stórais. settings.delete=Scrios an Stóras seo settings.delete_desc=Tá scriosadh stóras buan agus ní féidir é a chealú. settings.delete_notices_1=- NÍ FÉIDIR an oibríocht seo a chealú. +settings.delete_notices_2=- Scriosfaidh an oibríocht seo an stórlann %s go buan, lena n-áirítear cód, saincheisteanna, tuairimí, sonraí vicí agus socruithe comhoibrithe. settings.delete_notices_fork_1=- Beidh forcanna den stóras seo neamhspleách tar éis iad a scriosadh. settings.deletion_success=Tá an stóras scriosta. settings.update_settings_success=Nuashonraíodh na socruithe stóras. @@ -2272,6 +2327,8 @@ settings.team_not_in_organization=Níl an fhoireann san eagraíocht chéanna lei settings.teams=Foirne settings.add_team=Cuir Foireann leis settings.add_team_duplicate=Tá an stóras ag an bhfoireann cheana féin +settings.add_team_success=Tá rochtain ag an bhfoireann ar an stóras anois. +settings.change_team_permission_tip=Tá cead na foirne socraithe ar leathanach socruithe na foirne agus ní féidir é a athrú in aghaidh an stórais settings.delete_team_tip=Tá rochtain ag an bhfoireann seo ar gach stórais agus ní féidir í a bhaint settings.remove_team_success=Tá rochtain na foirne ar an stóras bainte amach. settings.add_webhook=Cuir Crúca Gréasán leis @@ -2536,6 +2593,7 @@ settings.archive.tagsettings_unavailable=Níl socruithe clibeanna ar fáil má t settings.archive.mirrors_unavailable=Níl scátháin ar fáil má tá an stóras i gcartlann. settings.unarchive.button=Stóras gan cartlann settings.unarchive.header=Díchartlannaigh an stóras seo +settings.unarchive.text=Má dhíchartlannaítear an stóras, athbhunófar a chumas chun gealltanais agus brúnna a fháil, chomh maith le saincheisteanna nua agus iarratais tarraingthe. settings.unarchive.success=Rinneadh an stóras a dhíchartlann go rathúil. settings.unarchive.error=Tharla earráid agus tú ag iarraidh an stóras a dhíchartlannú. Féach an logáil le haghaidh tuilleadh sonraí. settings.update_avatar_success=Nuashonraíodh avatar an stóras. @@ -2553,9 +2611,11 @@ settings.lfs_invalid_locking_path=Cosan neamhbhailí: %s settings.lfs_invalid_lock_directory=Ní féidir eolaire a ghlasáil: %s settings.lfs_lock_already_exists=Tá an glas ann cheana féin: %s settings.lfs_lock=Glas +settings.lfs_lock_path=Cosán comhaid le glasáil… settings.lfs_locks_no_locks=Gan Glais settings.lfs_lock_file_no_exist=Níl an comhad faoi ghlas sa bhrainse réamhshocraithe settings.lfs_force_unlock=Díghlasáil Fórsa +settings.lfs_pointers.found=Fuarthas %d pointeoir(í) bloba — %d gaolmhar, %d neamhghaolmhar (%d ar iarraidh ón stóras) settings.lfs_pointers.sha=SHA Blob settings.lfs_pointers.oid=OID settings.lfs_pointers.inRepo=I Stóras @@ -2713,6 +2773,7 @@ branch.new_branch_from=`Cruthaigh brainse nua ó "%s"` branch.renamed=Ainmníodh brainse %s go %s. branch.rename_default_or_protected_branch_error=Ní féidir ach le riarthóirí brainsí réamhshocraithe nó cosanta a athainmniú. branch.rename_protected_branch_failed=Tá an brainse seo faoi chosaint ag rialacha cosanta domhanda. +branch.commits_divergence_from=Difríocht tiomantais: %[1]d taobh thiar agus %[2]d chun tosaigh ar %[3]s branch.commits_no_divergence=Mar an gcéanna le brainse %[1]s tag.create_tag=Cruthaigh clib %s @@ -2737,6 +2798,7 @@ error.csv.invalid_field_count=Ní féidir an comhad seo a rindreáil toisc go bh error.broken_git_hook=Is cosúil go bhfuil crúcaí git den stór seo briste. Lean an doiciméadúchán chun iad a cheartú, ansin brúigh roinnt gealltanas chun an stádas a athnuachan. [graphs] +component_loading=Ag lódáil %s… component_loading_failed=Ní fhéadfaí %s a luchtú component_loading_info=Seans go dtógfaidh sé seo beagán… component_failed_to_load=Tharla earráid gan choinne. @@ -2775,6 +2837,7 @@ form.create_org_not_allowed=Níl cead agat eagraíocht a chruthú. settings=Socruithe settings.options=Eagraíocht settings.full_name=Ainm Iomlán +settings.email=Seoladh Ríomhphoist Teagmhála settings.website=Láithreán Gréasáin settings.location=Suíomh settings.permission=Ceadanna @@ -2791,7 +2854,10 @@ settings.update_setting_success=Nuashonraíodh socruithe eagraíochta. settings.rename=Athainmnigh an Eagraíocht settings.rename_desc=Má athraíonn tú ainm na heagraíochta, athrófar URL d’eagraíochta freisin agus saorfar an seanainm. +settings.rename_success=Athainmníodh an eagraíocht %[1]s go %[2]s go rathúil. +settings.rename_no_change=Níl ainm na heagraíochta athraithe. settings.rename_new_org_name=Ainm Nua na hEagraíochta +settings.rename_failed=Theip ar athainmniú na heagraíochta mar gheall ar earráid inmheánach settings.rename_notices_1=NÍ FÉIDIR an oibríocht seo a chealú. settings.rename_notices_2=Déanfar an seanainm a atreorú go dtí go n-éileofar é. @@ -2801,9 +2867,11 @@ settings.delete_account=Scrios an Eagraíocht seo settings.delete_prompt=Bainfear an eagraíocht go buan. NÍ FÉIDIR é seo a chealú! settings.name_confirm=Cuir isteach ainm na heagraíochta mar dheimhniú: settings.delete_notices_1=NÍ FÉIDIR an oibríocht seo a chealú. +settings.delete_notices_2=Scriosfaidh an oibríocht seo go buan gach stórais de chuid %s, lena n-áirítear cód, saincheisteanna, tuairimí, sonraí vicí agus socruithe comhoibritheora. settings.delete_notices_3=Scriosfaidh an oibríocht seo gach pacáiste de chuid %s go buan. settings.delete_notices_4=Scriosfaidh an oibríocht seo gach tionscadal de chuid %s go buan. settings.confirm_delete_account=Deimhnigh scriosadh +settings.delete_failed=Theip ar an eagraíocht a scriosadh mar gheall ar earráid inmheánach settings.delete_successful=Scriosadh an eagraíocht %s go rathúil. settings.hooks_desc=Cuir crúcaí gréasán in leis a spreagfar do gach stóras faoin eagraíocht seo. @@ -2860,6 +2928,7 @@ teams.remove_all_repos_title=Bain gach stórais foirne teams.remove_all_repos_desc=Bainfidh sé seo gach stórais ón bhfoireann. teams.add_all_repos_title=Cuir gach stórais leis teams.add_all_repos_desc=Cuirfidh sé seo stórais uile na heagraíochta leis an bhfoireann. +teams.add_nonexistent_repo=Níl an stóras atá tú ag iarraidh a chur leis ann. Cruthaigh í ar dtús le do thoil. teams.add_duplicate_users=Is ball foirne é an úsáideoir cheana féin. teams.repos.none=Ní raibh rochtain ag an bhfoireann seo ar aon stóras. teams.members.none=Níl aon bhaill ar an bhfoireann seo. @@ -2900,6 +2969,7 @@ repositories=Stórais hooks=Crúcaí Gréasán integrations=Comhtháthaithe authentication=Foinsí Fíordheimhnithe +emails=Seoltaí Ríomhphoist Úsáideoirí config=Cumraíocht config_summary=Achoimre config_settings=Socruithe @@ -2931,8 +3001,11 @@ dashboard.cron.cancelled=Cron: %[1]s cealaithe: %[3]s dashboard.cron.error=Earráid i gCron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s críochnaithe dashboard.delete_inactive_accounts=Scrios gach cuntas neamhghníomhach +dashboard.delete_inactive_accounts.started=Cuireadh tús leis an tasc chun na cuntais dhíghníomhachtaithe go léir a scriosadh dashboard.delete_repo_archives=Scrios gach cartlann stórais (ZIP, TAR.GZ, srl.) +dashboard.delete_repo_archives.started=Cuireadh tús leis an tasc chun gach cartlann stórtha a scriosadh dashboard.delete_missing_repos=Scrios gach stóras atá in easnamh ar a gcuid comhad Git +dashboard.delete_missing_repos.started=Cuireadh tús leis an tasc chun na stórais uile a scriosadh nach bhfuil a gcomhaid Git iontu dashboard.delete_generated_repository_avatars=Scrios abhatáranna stórtha ginte dashboard.sync_repo_branches=Sync brainsí caillte ó shonraí git go bunachair sonraí dashboard.sync_repo_tags=Clibeanna sioncraigh ó shonraí git go bunachar sonraí @@ -2940,7 +3013,12 @@ dashboard.update_mirrors=Scátháin a nuashonrú dashboard.repo_health_check=Seiceáil sláinte gach stóras dashboard.check_repo_stats=Seiceáil gach staitisticí stórais dashboard.archive_cleanup=Scrios sean-chartlanna stórais +dashboard.deleted_branches_cleanup=Glan suas brainsí scriosta dashboard.update_migration_poster_id=Nuashonraigh ID póstaer imir +dashboard.git_gc_repos=Bailitheoir bruscair gach stórais +dashboard.resync_all_sshkeys=Nuashonraigh an comhad '.ssh/authorized_keys' le heochracha SSH Gitea +dashboard.resync_all_sshprincipals=Nuashonraigh an comhad '.ssh/authorized_principals' le príomhoidí SSH Gitea +dashboard.resync_all_hooks=Athshioncrónaigh crúcaí réamhghlactha, nuashonraithe agus iarghlactha na stórais uile dashboard.reinit_missing_repos=Aththosaigh gach stórais Git atá in easnamh a bhfuil taifid ann dóibh dashboard.sync_external_users=Sioncrónaigh sonraí úsáideoirí seachtracha dashboard.cleanup_hook_task_table=Glan suas an tábla hook_task @@ -2976,8 +3054,10 @@ dashboard.total_gc_pause=Sos Iomlán GC dashboard.last_gc_pause=Sos GC Deireanach dashboard.gc_times=Amanna GC dashboard.delete_old_actions=Scrios gach sean-ghníomhaíocht ón mbunachar +dashboard.delete_old_actions.started=Scriosadh na seanghníomhaíochtaí go léir ón mbunachar sonraí tosaithe dashboard.update_checker=Seiceoir nuashonraithe dashboard.delete_old_system_notices=Scrios gach seanfhógra córais ón mbunachar sonraí +dashboard.gc_lfs=Bailitheoir bruscair meitea-réada LFS dashboard.stop_zombie_tasks=Stad gníomhartha tascanna zombie dashboard.stop_endless_tasks=Stad gníomhartha tascanna gan deireadh dashboard.cancel_abandoned_jobs=Cealaigh gníomhartha poist tréigthe @@ -3001,6 +3081,7 @@ users.2fa=2FA users.repos=Stórais users.created=Cruthaithe users.last_login=Sínigh Isteach Deiridh +users.never_login=Ná Sínigh Isteach riamh users.send_register_notify=Seol Fógra um Chlárú Úsáideora users.new_success=Tá an cuntas úsáideora "%s" cruthaithe. users.edit=Eagar @@ -3027,6 +3108,7 @@ users.still_own_repo=Tá stórais amháin nó níos mó fós ag an úsáideoir s users.still_has_org=Is ball d'eagraíocht é an t-úsáideoir seo. Bain an t-úsáideoir ó aon eagraíochtaí ar dtús. users.purge=Úsáideoir a Ghlanadh users.purge_help=Scrios go héigeantach úsáideoir agus aon stórais, eagraíochtaí agus pacáistí atá faoi úinéireacht an úsáideora. Scriosfar gach trácht freisin. +users.still_own_packages=Tá pacáiste amháin nó níos mó fós ag an úsáideoir seo. Scrios na pacáistí seo ar dtús. users.deletion_success=Scriosadh an cuntas úsáideora. users.reset_2fa=Athshocraigh 2FA users.list_status_filter.menu_text=Scagaire @@ -3046,7 +3128,11 @@ users.details=Sonraí Úsáideora emails.email_manage_panel=Bainistíocht Ríomhphost Úsáideoir emails.primary=Bunscoile emails.activated=Gníomhachtaithe +emails.filter_sort.email=Seoladh ríomhphoist +emails.filter_sort.email_reverse=Seoladh ríomhphoist (droim ar ais) emails.filter_sort.name=Ainm úsáideora +emails.filter_sort.name_reverse=Ainm úsáideora (droim ar ais) +emails.updated=Seoladh ríomhphoist nuashonraithe emails.not_updated=Theip ar an seoladh ríomhphoist iarrtha a nuashonrú: %v emails.duplicate_active=Tá an seoladh ríomhphoist seo gníomhach cheana féin d'úsáideoir difriúil. emails.change_email_header=Nuashonraigh Airíonna Ríomhphoist @@ -3054,6 +3140,7 @@ emails.change_email_text=An bhfuil tú cinnte gur mhaith leat an seoladh ríomhp emails.delete=Scrios Ríomhphost emails.delete_desc=An bhfuil tú cinnte gur mhaith leat an seoladh ríomhphoist seo a scriosadh? emails.deletion_success=Tá an seoladh ríomhphoist scriosta. +emails.delete_primary_email_error=Ní féidir leat an príomhsheoladh ríomhphoist a scriosadh. orgs.org_manage_panel=Bainistíocht Eagraíochta orgs.name=Ainm @@ -3167,20 +3254,29 @@ auths.oauth2_required_claim_name_helper=Socraigh an t-ainm seo chun logáil iste auths.oauth2_required_claim_value=Luach Éilimh Riachtanach auths.oauth2_required_claim_value_helper=Socraigh an luach seo chun logáil isteach ón bhfoinse seo a shrianadh chuig úsáideoirí a bhfuil éileamh acu leis an ainm agus an luach seo auths.oauth2_group_claim_name=Ainm éileamh ag soláthar ainmneacha grúpa don fhoinse seo (Roghnach) +auths.oauth2_full_name_claim_name=Ainm Iomlán Éilimh Ainm. (Roghnach — má shocraítear é, déanfar ainm iomlán an úsáideora a shioncrónú leis an éileamh seo i gcónaí) auths.oauth2_ssh_public_key_claim_name=Ainm Éilimh Eochrach Phoiblí SSH +auths.oauth2_admin_group=Luach Éilimh Ghrúpa d'úsáideoirí riarthóra. (Roghnach — éilítear ainm an éilimh thuas) +auths.oauth2_restricted_group=Luach Éilimh Ghrúpa d'úsáideoirí srianta. (Roghnach — éilítear ainm an éilimh thuas) +auths.oauth2_map_group_to_team=Mapáil grúpaí éilithe chuig foirne Eagraíochta. (Roghnach — éilítear ainm an éilimh thuas) auths.oauth2_map_group_to_team_removal=Bain úsáideoirí ó fhoirne sioncronaithe mura mbaineann an t-úsáideoir leis an ngrúpa comhfhreagrach. auths.enable_auto_register=Cumasaigh Clárú Auto auths.sspi_auto_create_users=Cruthaigh úsáideoirí go huathoibríoch +auths.sspi_auto_create_users_helper=Ceadaigh don mhodh údaraithe SSPI cuntais nua a chruthú go huathoibríoch d'úsáideoirí a logálann isteach den chéad uair auths.sspi_auto_activate_users=Gníomhachtaigh úsáideoirí go huathoibríoch auths.sspi_auto_activate_users_helper=Lig modh auth SSPI úsáideoirí nua a ghníomhachtú go huathoibríoch auths.sspi_strip_domain_names=Bain ainmneacha fearann ó ainm úsáideora +auths.sspi_strip_domain_names_helper=Má tá sé seo seiceáilte, bainfear ainmneacha fearainn as ainmneacha logála isteach (m.sh. ní bheidh ach "úsáideoir" i gceist le "DOMAIN\user" agus "user@example.org"). auths.sspi_separator_replacement=Deighilteoir le húsáid in ionad\,/agus @ +auths.sspi_separator_replacement_helper=An carachtar le húsáid chun deighilteoirí ainmneacha logála isteach ar leibhéal níos ísle (m.sh. an \ i "DOMAIN\user") agus príomhainmneacha úsáideora (m.sh. an @ i "user@example.org") a athsholáthar. auths.sspi_default_language=Teanga úsáideora réamhshocraithe +auths.sspi_default_language_helper=Teanga réamhshocraithe d'úsáideoirí a chruthaítear go huathoibríoch ag modh údaraithe SSPI. Fág folamh más fearr leat go mbraithfí an teanga go huathoibríoch. auths.tips=Leideanna auths.tips.oauth2.general=OAuth2 Fíordheimhniú auths.tips.oauth2.general.tip=Agus fíordheimhniú OAuth2 nua á chlárú agat, ba chóir go mbeadh an URL glaonna ais/atreoraithe: auths.tip.oauth2_provider=Soláthraí OAuth2 auths.tip.bitbucket=Cláraigh tomhaltóir OAuth nua ar %s agus cuir an cead 'Cuntas' - 'Léigh' leis +auths.tip.nextcloud=Cláraigh tomhaltóir OAuth nua ar do chás trí "Socruithe -> Slándáil -> Cliant OAuth 2.0" a roghnú sa roghchlár auths.tip.dropbox=Cruthaigh feidhmchlár nua ag %s auths.tip.facebook=Cláraigh feidhmchlár nua ag %s agus cuir an táirge "Facebook Login" leis auths.tip.github=Cláraigh feidhmchlár OAuth nua ar %s @@ -3290,6 +3386,7 @@ config.mailer_sendmail_path=Cosán Sendmail config.mailer_sendmail_args=Argóintí Breise chuig Sendmail config.mailer_sendmail_timeout=Teorainn Ama Sendmail config.mailer_use_dummy=Caochadán +config.test_email_placeholder=Seoladh Ríomhphoist (m.sh. test@example.com) config.send_test_mail=Seol Ríomhphost Tástála config.send_test_mail_submit=Seol config.test_mail_failed=Theip ar ríomhphost tástála a sheoladh chuig "%s": %v @@ -3378,6 +3475,7 @@ monitor.queue.numberinqueue=Uimhir i scuaine monitor.queue.review_add=Athbhreithniú / Cuir Oibrithe leis monitor.queue.settings.title=Socruithe Linn monitor.queue.settings.desc=Fásann linnte go dinimiciúil mar fhreagra ar a gcuid scuaine oibrithe a bhlocáil. +monitor.queue.settings.maxnumberworkers=Uasmhéid líon na n-oibrithe monitor.queue.settings.maxnumberworkers.placeholder=Faoi láthair %[1]d monitor.queue.settings.maxnumberworkers.error=Caithfidh uaslíon na n-oibrithe a bheith ina uimhir monitor.queue.settings.submit=Nuashonrú Socruithe @@ -3403,6 +3501,10 @@ notices.delete_success=Scriosadh na fógraí córais. self_check.no_problem_found=Níor aimsíodh aon fhadhb fós. self_check.startup_warnings=Rabhadh tosaithe: self_check.database_collation_mismatch=Bí ag súil le comhthiomsú a úsáid sa bhunachar sonraí: %s +self_check.database_collation_case_insensitive=Tá an bunachar sonraí ag baint úsáide as an gcóimheas %s, arb é atá ann ná cóimheas neamhíogair ó thaobh cás de. Cé gur féidir le Gitea oibriú leis, d'fhéadfadh go mbeadh roinnt cásanna neamhchoitianta ann nach n-oibreoidh mar a bhíothas ag súil leis. +self_check.database_inconsistent_collation_columns=Tá an bunachar sonraí ag úsáid an chóimheasa %s, ach tá na colúin seo ag úsáid chóimheasa mí-oiriúnacha. D’fhéadfadh sé seo roinnt fadhbanna gan choinne a chruthú. +self_check.database_fix_mysql=I gcás úsáideoirí MySQL/MariaDB, d'fhéadfá an t-ordú "gitea doctor convert" a úsáid chun na fadhbanna cóimheasa a shocrú, nó d'fhéadfá an fhadhb a shocrú de láimh le fiosrúcháin SQL "ALTER ... COLLATE ...". +self_check.database_fix_mssql=I gcás úsáideoirí MSSQL, ní fhéadfá an fhadhb a réiteach de láimh ach le fiosrúcháin SQL "ALTER ... COLLATE ..." faoi láthair. self_check.location_origin_mismatch=Ní mheaitseálann an URL reatha (%[1]s) an URL atá le feiceáil ag Gitea (%[2]s). Má tá seachfhreastalaí droim ar ais á úsáid agat, cinntigh le do thoil go bhfuil na ceanntásca "Óstríomhaire" agus "X-Forwarded-Proto" socraithe i gceart. [action] @@ -3486,6 +3588,8 @@ error.no_committer_account=Níl aon chuntas nasctha le seoladh ríomhphoist an t error.no_gpg_keys_found=Níor aimsíodh aon eochair aithne don síniú seo sa bhunachar error.not_signed_commit=Ní tiomantas sínithe error.failed_retrieval_gpg_keys=Theip ar aisghabháil eochair ar bith a bhí ceangailte le cuntas an tiomnóra +error.probable_bad_signature=RABHADH! Cé go bhfuil eochair leis an ID seo sa bhunachar sonraí, ní fhíoraíonn sé an tiomantas seo! Tá AMHRASACH ar an tiomantas seo. +error.probable_bad_default_signature=RABHADH! Cé go bhfuil an ID seo ag an eochair réamhshocraithe, ní fhíoraíonn sé an tiomantas seo! Tá AMHRASACH ar an tiomantas seo. [units] unit=Aonad @@ -3524,6 +3628,7 @@ versions.view_all=Féach ar gach dependency.id=ID dependency.version=Leagan search_in_external_registry=Cuardaigh i %s +alpine.registry=Socraigh an clárlann seo tríd an URL a chur i do chomhad /etc/apk/repositories: alpine.registry.key=Íoslódáil eochair RSA poiblí na clárlainne isteach san fhillteán /etc/apk/keys/ chun an síniú innéacs a fhíorú: alpine.registry.info=Roghnaigh $branch agus $repository ón liosta thíos. alpine.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas: @@ -3536,13 +3641,18 @@ arch.install=Sioncronaigh pacáiste le pacman: arch.repository=Eolas Stórais arch.repository.repositories=Stórais arch.repository.architectures=Ailtireachtaí +cargo.registry=Socraigh an clárlann seo i gcomhad cumraíochta Cargo (mar shampla ~/.cargo/config.toml): cargo.install=Chun an pacáiste a shuiteáil ag baint úsáide as Cargo, reáchtáil an t-ordú seo a leanas: +chef.registry=Socraigh an clárlann seo i do chomhad ~/.chef/config.rb: chef.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas: +composer.registry=Socraigh an chlár seo i do chomhad ~/.composer/config.json: composer.install=Chun an pacáiste a shuiteáil ag baint úsáide as Cumadóir, reáchtáil an t-ordú seo a leanas: composer.dependencies=Spleithiúlachtaí composer.dependencies.development=Spleithiúlachtaí Forbartha conan.details.repository=Stóras +conan.registry=Socraigh an clárlann seo ón líne ordaithe: conan.install=Chun an pacáiste a shuiteáil ag úsáid Conan, reáchtáil an t-ordú seo a leanas: +conda.registry=Socraigh an clárlann seo mar stóras Conda i do chomhad .condarc: conda.install=Chun an pacáiste a shuiteáil ag úsáid Conda, reáchtáil an t-ordú seo a leanas: container.details.type=Cineál Íomhá container.details.platform=Ardán @@ -3554,7 +3664,9 @@ container.layers=Sraitheanna Íomhá container.labels=Lipéid container.labels.key=Eochair container.labels.value=Luach +cran.registry=Socraigh an chlárlann seo i do chomhad Rprofile.site: cran.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas: +debian.registry=Socraigh an clárlann seo ón líne ordaithe: debian.registry.info=Roghnaigh $distribution agus $component ón liosta thíos. debian.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas: debian.repository=Eolas Stóras @@ -3563,11 +3675,16 @@ debian.repository.components=Comhpháirteanna debian.repository.architectures=Ailtireachtaí generic.download=Íoslódáil pacáiste ón líne ordaithe: go.install=Suiteáil an pacáiste ón líne ordaithe: +helm.registry=Socraigh an clárlann seo ón líne ordaithe: helm.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas: +maven.registry=Socraigh an clárlann seo i do chomhad pom.xml tionscadail: +maven.install=Chun an pacáiste a úsáid, cuir an méid seo a leanas san áireamh sa bhloc dependencies sa chomhad pom.xml: maven.install2=Rith tríd an líne ordaithe: maven.download=Chun an spleáchas a íoslódáil, rith tríd an líne ordaithe: +nuget.registry=Socraigh an clárlann seo ón líne ordaithe: nuget.install=Chun an pacáiste a shuiteáil ag úsáid NuGet, reáchtáil an t-ordú seo a leanas: nuget.dependency.framework=Spriocchreat +npm.registry=Socraigh an chlárlann seo i do chomhad .npmrc do thionscadail: npm.install=Chun an pacáiste a shuiteáil ag úsáid npm, reáchtáil an t-ordú seo a leanas: npm.install2=nó cuir leis an gcomhad package.json é: npm.dependencies=Spleithiúlachtaí @@ -3579,6 +3696,7 @@ npm.details.tag=Clib pub.install=Chun an pacáiste a shuiteáil ag úsáid Dart, reáchtáil an t-ordú seo a leanas: pypi.requires=Teastaíonn Python pypi.install=Chun an pacáiste a shuiteáil ag úsáid pip, reáchtáil an t-ordú seo a leanas: +rpm.registry=Socraigh an clárlann seo ón líne ordaithe: rpm.distros.redhat=ar dháileadh bunaithe ar RedHat rpm.distros.suse=ar dháileadh bunaithe ar SUSE rpm.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas: @@ -3591,6 +3709,7 @@ rubygems.dependencies.runtime=Spleáchais Rith-Ama rubygems.dependencies.development=Spleáchais Forbartha rubygems.required.ruby=Éilíonn leagan Ruby rubygems.required.rubygems=Éilíonn leagan RubyGem +swift.registry=Socraigh an clárlann seo ón líne ordaithe: swift.install=Cuir an pacáiste i do chomhad Package.swift: swift.install2=agus reáchtáil an t-ordú seo a leanas: vagrant.install=Chun bosca Vagrant a chur leis, reáchtáil an t-ordú seo a leanas: diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 55595fb4c8c..312e0dd4f12 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -44,6 +44,7 @@ webauthn_use_twofa=携帯電話から2要素認証コードを使用する webauthn_error=セキュリティキーを読み取ることができません。 webauthn_unsupported_browser=お使いのブラウザは現在 WebAuthn をサポートしていません。 webauthn_error_unknown=不明なエラーが発生しました。 もう一度やり直してください。 +webauthn_error_insecure=WebAuthn は安全な接続でのみ使用できます。 HTTPでのテストには "localhost" または "127.0.0.1" のオリジンが使用できます。 webauthn_error_unable_to_process=サーバーがリクエストを処理できませんでした。 webauthn_error_duplicated=このリクエストに対しては、許可されていないセキュリティキーです。 キーが未登録であることを確認してください。 webauthn_error_empty=このキーに名前を設定する必要があります。 @@ -116,6 +117,7 @@ files=ファイル error=エラー error404=アクセスしようとしたページは存在しないか、閲覧が許可されていません。 +error503=サーバーはリクエストを完了できませんでした。 後でもう一度お試しください。 go_back=戻る invalid_data=無効なデータ: %v @@ -129,6 +131,7 @@ unpin=ピン留め解除 artifacts=成果物 expired=期限切れ +confirm_delete_artifact=アーティファクト '%s' を削除してよろしいですか? archived=アーカイブ @@ -165,18 +168,33 @@ no_results_found=見つかりません。 internal_error_skipped=内部エラーが発生しましたがスキップされました: %s [search] +search=検索… type_tooltip=検索タイプ fuzzy=あいまい +fuzzy_tooltip=検索語に近い結果も含めます words=単語 words_tooltip=検索語と一致する結果だけを含めます regexp=正規表現 regexp_tooltip=正規表現検索パターンと一致する結果だけを含めます exact=完全一致 exact_tooltip=検索語と完全に一致する結果だけを含めます +repo_kind=リポジトリを検索… +user_kind=ユーザーを検索… +org_kind=組織を検索… +team_kind=チームを検索… +code_kind=コードを検索… code_search_unavailable=コード検索は現在利用できません。 サイト管理者にお問い合わせください。 code_search_by_git_grep=現在のコード検索は "git grep" によって行われています。 サイト管理者がリポジトリインデクサーを有効にすれば、より優れた結果が得られる可能性があります。 +package_kind=パッケージを検索… +project_kind=プロジェクトを検索… +branch_kind=ブランチを検索… +tag_kind=タグを検索… tag_tooltip=一致するタグを検索します。任意のシーケンスに一致させるには '%' を使用してください。 +commit_kind=コミットを検索… +runner_kind=ランナーを検索… no_results=一致する結果が見つかりませんでした +issue_kind=イシューを検索… +pull_kind=プルリクエストを検索… keyword_search_unavailable=キーワード検索は現在利用できません。 サイト管理者にお問い合わせください。 [aria] @@ -212,6 +230,8 @@ buttons.enable_monospace_font=等幅フォントを有効にする buttons.disable_monospace_font=等幅フォントを無効にする [filter] +string.asc=A–Z +string.desc=Z–A [error] occurred=エラーが発生しました @@ -232,6 +252,7 @@ license_desc=Go get %[ [install] install=インストール +installing_desc=インストール中です、お待ちください… title=初期設定 docker_helper=GiteaをDocker内で実行する場合は、設定を変更する前にドキュメントを読んでください。 require_db_desc=Giteaには、MySQL、PostgreSQL、MSSQL、SQLite3、またはTiDB(MySQL プロトコル) が必要です。 @@ -248,10 +269,16 @@ path=パス sqlite_helper=SQLite3のデータベースファイルパス。
Giteaをサービスとして実行する場合は絶対パスを入力します。 reinstall_error=既存のGiteaデータベースへインストールしようとしています reinstall_confirm_message=既存のGiteaデータベースに再インストールすると、複数の問題が発生する可能性があります。 たいていの場合は、既存の"app.ini"を使用してGiteaを実行すべきです。 何をしているか分かっている場合は、以下を確認してください。 +reinstall_confirm_check_1=App.ini 内の SECRET_KEY により暗号化されたデータは失われる可能性があります: ユーザーが 2FA/OTP でログインできなかったり、ミラーが正しく機能しない可能性があります。 このボックスにチェックをいれた場合は、現在のapp.iniファイルには正しいSECRET_KEYが含まれているものとします。 +reinstall_confirm_check_2=リポジトリと設定の再同期が必要になる場合があります。 このボックスにチェックをいれた場合、リポジトリのフックと authorized_keys ファイルはあなたが手動で再設定するものとします。 またリポジトリとミラーの設定も、あなたが正しく設定するものとします。 reinstall_confirm_check_3=このGiteaが正しい場所にある app.ini で動作しており、確実に再インストールの必要性があるものとします。 あなたは上記のリスクを承知しています。 err_empty_db_path=SQLite3のデータベースパスを空にすることはできません。 no_admin_and_disable_registration=管理者アカウントを作成せずに、セルフ登録を無効にすることはできません。 err_empty_admin_password=管理者パスワードは空にできません。 +err_empty_admin_email=管理者のメールアドレスは空にできません。 +err_admin_name_is_reserved=管理者のユーザー名が不正です。予約済みのユーザー名です。 +err_admin_name_pattern_not_allowed=管理者のユーザー名が不正です。 予約済みのパターンにマッチしています。 +err_admin_name_is_invalid=管理者のユーザー名が不正です general_title=基本設定 app_name=サイトタイトル @@ -267,6 +294,7 @@ domain_helper=サーバーのドメインまたはホストアドレス。 ssh_port=SSHサーバーのポート ssh_port_helper=SSHサーバーが使うポート番号。 空の場合はSSHサーバーを無効にします。 http_port=Gitea HTTPポート +http_port_helper=GiteaのWebサーバーが接続待ちするポート番号。 app_url=GiteaのベースURL app_url_helper=HTTP(S)のクローンURLとメール通知で使うベースアドレス。 log_root_path=ログの保存先パス @@ -330,6 +358,7 @@ no_reply_address=メールを隠すときのドメイン no_reply_address_helper=メールアドレスを隠しているユーザーに使用するドメイン名。 例えば 'noreply.example.org' と設定した場合、ユーザー名 'joe' はGitに 'joe@noreply.example.org' としてログインすることになります。 password_algorithm=パスワードハッシュアルゴリズム invalid_password_algorithm=無効なパスワードハッシュアルゴリズム +password_algorithm_helper=パスワードハッシュアルゴリズムを設定します。 アルゴリズムにより動作要件と強度が異なります。 argon2アルゴリズムはかなり安全ですが、多くのメモリを使用するため小さなシステムには適さない場合があります。 enable_update_checker=アップデートチェッカーを有効にする enable_update_checker_helper=gitea.ioに接続して定期的に新しいバージョンのリリースを確認します。 env_config_keys=環境設定 @@ -401,6 +430,8 @@ allow_password_change=ユーザーはパスワードの変更が必要 (推奨) reset_password_mail_sent_prompt=%s に確認メールを送信しました。 %s以内に受信トレイを確認し、アカウント回復手続きを完了してください。 active_your_account=アカウントの有効化 account_activated=アカウントがアクティベートされました +prohibit_login=サインイン禁止 +prohibit_login_desc=あなたのアカウントはサインインを禁止されています。 サイト管理者にお問い合わせください。 resent_limit_prompt=少し前に、あなたからアクティベーションメールが要求されています。 3分待ったのち、もう一度試してください。 has_unconfirmed_mail=こんにちは %s さん、あなたのメール アドレス (%s) は確認がとれていません。 確認メールを受け取っていない場合や、改めて送信したい場合は、下のボタンをクリックしてください。 change_unconfirmed_mail_address=登録のメールアドレスが間違っている場合は、こちらで変更して新しい確認メールを再送信することができます。 @@ -421,6 +452,7 @@ use_scratch_code=スクラッチコードを使う twofa_scratch_used=あなたはスクラッチコードを使用しました。 2要素認証の設定ページにリダイレクトしましたので、デバイスの登録を解除するか、新しいスクラッチコードを生成しましょう。 twofa_passcode_incorrect=パスコードが正しくありません。デバイスを紛失した場合は、スクラッチコードを使ってサインインしてください。 twofa_scratch_token_incorrect=スクラッチコードが正しくありません。 +twofa_required=リポジトリにアクセスするには2段階認証を設定するか、再度ログインしてください。 login_userpass=サインイン login_openid=OpenID oauth_signup_tab=新規アカウント登録 @@ -432,19 +464,24 @@ oauth_signin_submit=アカウントにリンク oauth.signin.error.general=認可リクエストの処理中にエラーが発生しました: %s 。このエラーが解決しない場合は、サイト管理者に問い合わせてください。 oauth.signin.error.access_denied=認可リクエストが拒否されました。 oauth.signin.error.temporarily_unavailable=認証サーバーが一時的に利用できないため、認可に失敗しました。後でもう一度やり直してください。 +oauth_callback_unable_auto_reg=自動登録が有効になっていますが、OAuth2プロバイダー %[1]s の応答はフィールド %[2]s が不足しており、自動でアカウントを作成することができません。 アカウントの作成や連携を行うか、サイト管理者にお問い合わせください。 openid_connect_submit=接続 openid_connect_title=既存のアカウントに接続 openid_connect_desc=選択したOpenID URIは未登録です。 ここで新しいアカウントと関連付けます。 openid_register_title=アカウント新規作成 openid_register_desc=選択したOpenID URIは未登録です。 ここで新しいアカウントと関連付けます。 openid_signin_desc=OpenID URIを入力します。例: alice.openid.example.org または https://openid.example.org/alice +disable_forgot_password_mail=メールアドレスが設定されていないためアカウントの回復は無効になっています。 サイト管理者にお問い合わせください。 +disable_forgot_password_mail_admin=アカウントの回復はメールアドレスが設定済みの場合だけ使用できます。 email_domain_blacklisted=あなたのメールアドレスでは登録することはできません。 authorize_application=アプリケーションを許可 authorize_redirect_notice=このアプリケーションを許可すると %s にリダイレクトします。 authorize_application_created_by=このアプリケーションは %s が作成しました。 +authorize_application_description=アクセスを許可すると、このアプリケーションは、プライベート リポジトリや組織を含むあなたのすべてのアカウント情報に対して、アクセスと書き込みができるようになります。 authorize_application_with_scopes=スコープ: %s authorize_title=`"%s"にあなたのアカウントへのアクセスを許可しますか?` authorization_failed=認可失敗 +authorization_failed_desc=無効なリクエストを検出したため認可が失敗しました。 認可しようとしたアプリの開発者に連絡してください。 sspi_auth_failed=SSPI認証に失敗しました password_pwned=あなたが選択したパスワードは、過去の情報漏洩事件で流出した盗まれたパスワードのリストに含まれています。 別のパスワードでもう一度試してください。 また他の登録でもこのパスワードからの変更を検討してください。 password_pwned_err=HaveIBeenPwnedへのリクエストを完了できませんでした @@ -469,6 +506,8 @@ activate_email.text=あなたのメールアドレスを確認するため、 register_notify=%s へようこそ register_notify.title=%[1]s さん、%[2]s にようこそ +register_notify.text_1=これは %s への登録確認メールです! +register_notify.text_2=あなたはユーザー名 %s でログインできるようになりました。 register_notify.text_3=このアカウントがあなたに作成されたものであれば、最初にパスワードを設定してください。 reset_password=アカウントを回復 @@ -506,6 +545,7 @@ release.download.targz=ソースコード (TAR.GZ) repo.transfer.subject_to=%s が "%s" を %s に移転しようとしています repo.transfer.subject_to_you=%s が "%s" をあなたに移転しようとしています repo.transfer.to_you=あなた +repo.transfer.body=承認または拒否するには %s を開きます。 もしくは単に無視してもかまいません。 repo.collaborator.added.subject=%s が %s にあなたを追加しました repo.collaborator.added.text=あなたは次のリポジトリの共同作業者に追加されました: @@ -557,6 +597,7 @@ url_error=`"%s" は有効なURLではありません。` include_error=`は文字列 "%s" を含んでいる必要があります。` glob_pattern_error=`のglobパターンが不正です: %s.` regex_pattern_error=`の正規表現パターンが不正です: %s.` +username_error=`は、英数字('0-9','a-z','A-Z')、ダッシュ('-')、アンダースコア('_')、ドット('.')だけを含めることができます。 先頭と末尾は英数字以外の文字にはできません。 また、連続した英数字以外の文字も許されません。` invalid_group_team_map_error=`のマッピングが無効です: %s` unknown_error=不明なエラー: captcha_incorrect=CAPTCHAコードが正しくありません。 @@ -570,15 +611,18 @@ change_full_name_disabled=フルネームの変更は無効化されています username_has_not_been_changed=ユーザー名は変更されていません repo_name_been_taken=リポジトリ名が既に使用されています。 repository_force_private=強制プライベートが有効です。プライベートリポジトリはパブリックにできません。 -repository_files_already_exist=このリポジトリのファイルはすでに存在します。システム管理者に問い合わせてください。 -repository_files_already_exist.delete=このリポジトリのファイルはすでに存在しています。 それらを削除する必要があります。 -repository_files_already_exist.adopt_or_delete=このリポジトリのファイルはすでに存在しています。 それらを登録するか削除してください。 +repository_files_already_exist=このリポジトリには既にファイルが存在しています。システム管理者に問い合わせてください。 +repository_files_already_exist.adopt=このリポジトリには既にファイルが存在しており、それらを取り込むことはできます。 +repository_files_already_exist.delete=このリポジトリには既にファイルが存在しています。 それらを削除する必要があります。 +repository_files_already_exist.adopt_or_delete=このリポジトリには既にファイルが存在しています。 それらを取り込むか削除してください。 visit_rate_limit=相手側でアクセス数制限されています。 +2fa_auth_required=相手側へのアクセスに2要素認証が必要です。 org_name_been_taken=組織名が既に使用されています。 team_name_been_taken=チーム名が既に使用されています。 team_no_units_error=リポジトリセクションは、少なくともひとつはアクセスを許可してください。 email_been_used=メールアドレスが既に使用されています。 email_invalid=メールアドレスが不正です。 +email_domain_is_not_allowed=ユーザーのメールアドレス %s のドメインが、EMAIL_DOMAIN_ALLOWLIST または EMAIL_DOMAIN_BLOCKLIST に違反しています。 あなたの操作が適切なものであるか確認してください。 openid_been_used=OpenIDのアドレス "%s" は既に使用されています。 username_password_incorrect=ユーザー名またはパスワードが間違っています。 password_complexity=パスワードが複雑性の要件を満たしていません: @@ -603,8 +647,14 @@ invalid_ssh_key=SSHキーが確認できません: %s invalid_gpg_key=GPGキーが確認できません: %s invalid_ssh_principal=無効なプリンシパル: %s must_use_public_key=あなたが提供したキーは秘密鍵です。秘密鍵をどこにもアップロードしないでください。代わりに公開鍵を使用してください。 +unable_verify_ssh_key=SSHキーが確認できません。間違いが無いかよく確認してください。 auth_failed=認証に失敗しました: %v +still_own_repo=あなたのアカウントは1つ以上のリポジトリを所有しています。 先にそれらを削除するか移転してください。 +still_has_org=あなたのアカウントは1つ以上の組織に参加しています。 先にそれらから脱退してください。 +still_own_packages=あなたのアカウントは1つ以上のパッケージを所有しています。 先にそれらを削除してください。 +org_still_own_repo=組織はまだ1つ以上のリポジトリを所有しています。 先にそれらを削除するか移転してください。 +org_still_own_packages=組織はまだ1つ以上のパッケージを所有しています。 先にそれらを削除してください。 target_branch_not_exist=ターゲットのブランチが存在していません。 target_ref_not_exist=ターゲットの ref が存在しません %s @@ -629,15 +679,17 @@ unfollow=フォロー解除 user_bio=経歴 disabled_public_activity=このユーザーはアクティビティ表示を公開していません。 email_visibility.limited=あなたのメールアドレスはすべての認証済みユーザーに表示されています -email_visibility.private=あなたのメールアドレスは、あなたと管理者のみに表示されます +email_visibility.private=あなたのメールアドレスは、あなたと管理者にのみ表示されます show_on_map=地図上にこの場所を表示 settings=ユーザー設定 form.name_reserved=ユーザー名 "%s" は予約されています。 form.name_pattern_not_allowed=`"%s" の形式はユーザー名に使用できません。` +form.name_chars_not_allowed=ユーザー名 "%s" には無効な文字が含まれています。 block.block=ブロック block.block.user=ユーザーをブロック +block.block.org=組織向けにユーザーをブロック block.block.failure=ユーザーのブロックに失敗しました: %s block.unblock=ブロックを解除 block.unblock.failure=ユーザーのブロック解除に失敗しました: %s @@ -650,6 +702,7 @@ block.info_3=あなたのユーザー名で@メンションして通知を送る block.info_4=そのユーザーのリポジトリに、あなたを共同作業者として招待すること block.info_5=リポジトリへの、スター、フォーク、ウォッチ block.info_6=イシューやプルリクエストの作成、コメント投稿 +block.info_7=イシューやプルリクエストでの、あなたのコメントに対するリアクションの送信 block.user_to_block=ブロックするユーザー block.note=メモ block.note.title=メモ(任意): @@ -680,6 +733,7 @@ webauthn=2要素認証 (セキュリティキー) public_profile=公開プロフィール biography_placeholder=自己紹介してください!(Markdownを使うことができます) location_placeholder=おおよその場所を他の人と共有 +profile_desc=あなたのプロフィールが他のユーザーにどのように表示されるかを制御します。あなたのプライマリメールアドレスは、通知、パスワードの回復、WebベースのGit操作に使用されます。 password_username_disabled=ユーザー名の変更は許可されていません。詳細はサイト管理者にお問い合わせください。 password_full_name_disabled=フルネームの変更は許可されていません。詳細はサイト管理者にお問い合わせください。 full_name=フルネーム @@ -699,6 +753,7 @@ cancel=キャンセル language=言語 ui=テーマ hidden_comment_types=非表示にするコメントの種類 +hidden_comment_types_description=ここでチェックを入れたコメントの種類は、イシューのページには表示されません。 たとえば「ラベル」にチェックを入れると、「{ユーザー} が {ラベル} を追加/削除」といったコメントはすべて除外されます。 hidden_comment_types.ref_tooltip=このイシューが別のイシューやコミット等から参照された、というコメント hidden_comment_types.issue_ref_tooltip=このイシューのブランチやタグへの関連付けをユーザーが変更した、というコメント comment_type_group_reference=参照 @@ -746,14 +801,18 @@ manage_themes=デフォルトのテーマを選択 manage_openid=OpenIDアドレスの管理 email_desc=プライマリメールアドレスは、通知、パスワードの回復、さらにメールアドレスを隠さない場合は、WebベースのGit操作にも使用されます。 theme_desc=この設定がサイト全体のデフォルトのテーマとなります。 +theme_colorblindness_help=色覚障害テーマのサポート +theme_colorblindness_prompt=Giteaには基本的な色覚障害サポートを含むテーマがいくつか入っていますが、それらは色定義が少ししかありません。 作業はまだ進行中です。 テーマCSSファイルにもっと多くの色を定義していくことで、さらに改善できる余地があります。 primary=プライマリー activated=アクティベート済み requires_activation=アクティベーションが必要 primary_email=プライマリーにする activate_email=アクティベーションを送信 activations_pending=アクティベーション待ち +can_not_add_email_activations_pending=保留中のアクティベーションがあります。新しいメールを追加する場合は、数分後にもう一度お試しください。 delete_email=削除 email_deletion=メールアドレスの削除 +email_deletion_desc=このメールアドレスと関連情報をアカウントから削除します。 このメールアドレスを使ったGitのコミットはそのまま残ります。 続行しますか? email_deletion_success=メールアドレスを削除しました。 theme_update_success=テーマを更新しました。 theme_update_error=選択されたテーマが存在しません。 @@ -796,6 +855,7 @@ gpg_key_matched_identities_long=次のアクティベート済みメールアド gpg_key_verified=確認済みの鍵 gpg_key_verified_long=鍵はトークンを使用して確認済みです。 鍵のIDに一致するコミットだけでなく、このユーザーのいずれかのアクティベート済みメールアドレスに一致するコミットについても、この鍵を使用して検証することができます。 gpg_key_verify=確認 +gpg_invalid_token_signature=入力されたGPG鍵、署名、トークンが合致しないか、トークンが古いです。 gpg_token_required=以下のトークンの署名を入力する必要があります gpg_token=トークン gpg_token_help=署名はこの方法で生成できます: @@ -805,6 +865,7 @@ verify_gpg_key_success=GPG鍵 "%s" を確認しました。 ssh_key_verified=確認済みの鍵 ssh_key_verified_long=鍵はトークンを使用して確認済みです。このユーザーのいずれかのアクティベート済みメールアドレスに一致するコミットについても、この鍵を使用して検証することができます。 ssh_key_verify=確認 +ssh_invalid_token_signature=入力されたSSH 鍵、署名、トークンが合致しないか、トークンが古いです。 ssh_token_required=以下のトークンの署名を入力する必要があります ssh_token=トークン ssh_token_help=署名はこの方法で生成できます: @@ -825,6 +886,7 @@ gpg_key_deletion=GPGキーの削除 ssh_principal_deletion=SSH証明書プリンシパルの削除 ssh_key_deletion_desc=SSHキーを削除して、アカウントへのアクセスを無効にします。 続行しますか? gpg_key_deletion_desc=GPGキーを削除すると、そのキーで署名したコミットは未検証となります。 続行しますか? +ssh_principal_deletion_desc=SSH証明書プリンシパルを削除して、アカウントへのアクセスを無効にします。 続行しますか? ssh_key_deletion_success=SSHキーを削除しました。 gpg_key_deletion_success=GPGキーを削除しました。 ssh_principal_deletion_success=プリンシパルを削除しました。 @@ -886,6 +948,7 @@ create_oauth2_application_button=アプリケーション作成 create_oauth2_application_success=新しいOAuth2アプリケーションを作成しました。 update_oauth2_application_success=OAuth2アプリケーションを更新しました。 oauth2_application_name=アプリケーション名 +oauth2_confidential_client=コンフィデンシャルクライアント。 ウェブアプリのように秘密情報を機密にできるアプリの場合に選択します。 デスクトップアプリやモバイルアプリなどのネイティブアプリには選択しないでください。 oauth2_skip_secondary_authorization=一度アクセスを許可した後、公開クライアントの認証をスキップします。 セキュリティ上のリスクが生じる可能性があります。 oauth2_redirect_uris=リダイレクトURI (複数可)。 URIごとに改行してください。 save_application=保存 @@ -958,14 +1021,16 @@ email_notifications.onmention=メンションのみメール通知 email_notifications.disable=メール通知無効 email_notifications.submit=メール設定を保存 email_notifications.andyourown=自分に関する通知も含める +email_notifications.actions.desc=Gitea Actionsが設定されたリポジトリのワークフロー実行に関する通知。 +email_notifications.actions.failure_only=失敗したワークフロー実行についてのみ通知 visibility=ユーザーの公開範囲 visibility.public=パブリック visibility.public_tooltip=全員に表示されます visibility.limited=限定 -visibility.limited_tooltip=認証されたユーザーのみに表示されます +visibility.limited_tooltip=認証されたユーザーにのみ表示されます visibility.private=プライベート -visibility.private_tooltip=あなたが参加した組織のメンバーのみに表示されます +visibility.private_tooltip=あなたが参加した組織のメンバーにのみ表示されます [repo] new_repo_helper=リポジトリには、プロジェクトのすべてのファイルとリビジョン履歴が入ります。 すでにほかの場所でホストしていますか? リポジトリを移行 もどうぞ。 @@ -1166,6 +1231,7 @@ migrate.migrating_issues=イシュー移行中 migrate.migrating_pulls=プルリクエスト移行中 migrate.cancel_migrating_title=移行のキャンセル migrate.cancel_migrating_confirm=この移行をキャンセルしますか? +migration_status=移行状況 mirror_from=ミラー元 forked_from=フォーク元 @@ -2101,6 +2167,7 @@ settings.collaboration.write=書き込み settings.collaboration.read=読み取り settings.collaboration.owner=オーナー settings.collaboration.undefined=未定義 +settings.collaboration.per_unit=ユニット権限 settings.hooks=Webhook settings.githooks=Gitフック settings.basic_settings=基本設定 @@ -2254,7 +2321,7 @@ settings.collaborator_deletion=共同作業者の削除 settings.collaborator_deletion_desc=共同作業者を削除し、このリポジトリへのアクセス権を取り消します。 続行しますか? settings.remove_collaborator_success=共同作業者を削除しました。 settings.org_not_allowed_to_be_collaborator=組織を共同作業者として追加することはできません。 -settings.change_team_access_not_allowed=リポジトリに対するチームアクセス権の変更は、組織のオーナーのみに制限されています。 +settings.change_team_access_not_allowed=リポジトリに対するチームアクセス権の変更は、組織のオーナーにのみ制限されています。 settings.team_not_in_organization=チームがリポジトリと同じ組織に属していません。 settings.teams=チーム settings.add_team=チームを追加 @@ -2505,7 +2572,7 @@ settings.matrix.message_type=メッセージ種別 settings.visibility.private.button=プライベートにする settings.visibility.private.text=プライベートに変更することで、リポジトリは許可されたメンバーにのみ表示されるようになり、既存のフォーク、ウォッチャー、スターとの関係は解除される可能性があります。 settings.visibility.private.bullet_title=プライベートに変更すると: -settings.visibility.private.bullet_one=許可されたメンバーのみにリポジトリを表示します。 +settings.visibility.private.bullet_one=許可されたメンバーにのみリポジトリを表示します。 settings.visibility.private.bullet_two=フォーク、ウォッチャー、スターとの関係を解除する可能性があります。 settings.visibility.public.button=公開する settings.visibility.public.text=公開に変更すると、リポジトリを誰でも閲覧できるようにします。 @@ -2705,6 +2772,8 @@ branch.new_branch_from=`"%s" から新しいブランチを作成` branch.renamed=ブランチ %s は %s にリネームされました。 branch.rename_default_or_protected_branch_error=デフォルトブランチや保護ブランチのリネームが可能なのは管理者だけです。 branch.rename_protected_branch_failed=このブランチはglobベースの保護ルールに従って保護されています。 +branch.commits_divergence_from=コミットの乖離: %[3]s より %[1]d 件遅れ %[2]d 件先行 +branch.commits_no_divergence=%[1]s ブランチと一致 tag.create_tag=タグ %s を作成 tag.create_tag_operation=タグの作成 @@ -2718,6 +2787,7 @@ topic.done=完了 topic.count_prompt=選択できるのは25トピックまでです。 topic.format_prompt=トピック名は英字または数字で始め、ダッシュ('-')やドット('.')を含めることができます。最大35文字までです。文字は小文字でなければなりません。 +find_file.follow_symlink=シンボリックリンクが指し示す先を開く find_file.go_to_file=ファイルへ移動 find_file.no_matching=一致するファイルが見つかりません @@ -3183,6 +3253,8 @@ auths.oauth2_required_claim_name_helper=このClaim名を設定すると、こ auths.oauth2_required_claim_value=必須Claim値 auths.oauth2_required_claim_value_helper=この値を設定すると、このソースからのログインを、指定したClaim名とClaim値を持つユーザーに限定します。 auths.oauth2_group_claim_name=このソースでグループ名を提供するClaim名 (オプション) +auths.oauth2_full_name_claim_name=フルネームのClaim名。 (オプション — 設定すると、ユーザーのフルネームは常にこのClaimに同期します) +auths.oauth2_ssh_public_key_claim_name=SSH公開鍵のClaim名 auths.oauth2_admin_group=管理者ユーザーのグループClaim値 (オプション — 上のClaim名が必要) auths.oauth2_restricted_group=制限付きユーザーのグループClaim値 (オプション — 上のClaim名が必要) auths.oauth2_map_group_to_team=見つかったグループを組織のチームにマップ (オプション — 上のClaim名が必要) diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index cc571816ac4..c60edda73f2 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -8,7 +8,7 @@ sign_in_with_provider=Entrar com %s sign_in_or=ou sign_out=Sair sign_up=Cadastrar -link_account=Vincular conta +link_account=Vincular Conta register=Cadastrar version=Versão powered_by=Desenvolvido por %s @@ -16,7 +16,8 @@ page=Página template=Template language=Idioma notifications=Notificações -active_stopwatch=Cronômetro ativo +active_stopwatch=Cronômetro Ativo +tracked_time_summary=Resumo do tempo monitorado com base nos filtros da lista de problemas create_new=Criar… user_profile_and_more=Perfil e Configurações... signed_in_as=Acessado como @@ -24,24 +25,26 @@ enable_javascript=Este site requer JavaScript. toc=Índice licenses=Licenças return_to_gitea=Volte para Gitea +more_items=Mais itens username=Nome de usuário -email=Endereço de e-mail +email=Endereço de E-mail password=Senha access_token=Token de Acesso -re_type=Confirmar senha +re_type=Confirmar Senha captcha=CAPTCHA -twofa=Autenticação de dois fatores -twofa_scratch=Código de backup da autenticação de dois fatores +twofa=Autenticação de Dois Fatores +twofa_scratch=Código de Backup da Autenticação de Dois Fatores passcode=Senha webauthn_insert_key=Insira sua chave de segurança webauthn_sign_in=Pressione o botão na sua chave de segurança. Se a sua chave de segurança não tiver um botão, insira-a novamente. webauthn_press_button=Por favor, pressione o botão na sua chave de segurança… -webauthn_use_twofa=Use um código de duas etapas do seu telefone +webauthn_use_twofa=Use um código de dois fatores do seu telefone webauthn_error=Não foi possível ler sua chave de segurança. webauthn_unsupported_browser=Seu navegador não oferece suporte ao WebAuthn. webauthn_error_unknown=Ocorreu um erro desconhecido. Por favor, tente novamente. +webauthn_error_insecure=`WebAuthn suporta apenas conexões seguras. Para testar via HTTP, você pode usar a origem "localhost" ou "127.0.0.1"` webauthn_error_unable_to_process=O servidor não pôde processar sua solicitação. webauthn_error_duplicated=A chave de segurança não é permitida para esta solicitação. Por favor, certifique-se que a chave já não está registrada. webauthn_error_empty=Você deve definir um nome para esta chave. @@ -52,16 +55,16 @@ repository=Repositório organization=Organização mirror=Espelhamento issue_milestone=Marco -new_repo=Novo repositório -new_migrate=Nova migração -new_mirror=Novo espelhamento +new_repo=Novo Repositório +new_migrate=Nova Migração +new_mirror=Novo Espelhamento new_fork=Novo Fork de Repositório -new_org=Nova organização +new_org=Nova Organização new_project=Novo Projeto new_project_column=Nova Coluna -manage_org=Gerenciar organizações -admin_panel=Administração geral -account_settings=Configurações da conta +manage_org=Gerenciar Organizações +admin_panel=Administração Geral +account_settings=Configurações da Conta settings=Configurações your_profile=Perfil your_starred=Favorito @@ -74,7 +77,7 @@ collaborative=Colaborativo forks=Forks activities=Atividades -pull_requests=Pull requests +pull_requests=Pull Requests issues=Issues milestones=Marcos @@ -85,12 +88,13 @@ rerun=Reexecutar rerun_all=Reexecutar todas as tarefas save=Salvar add=Adicionar -add_all=Adicionar todos +add_all=Adicionar Todos remove=Remover -remove_all=Excluir todos +remove_all=Excluir Todos remove_label_str=`Remover item "%s"` edit=Editar view=Visualizar +test=Teste enabled=Habilitado disabled=Desabilitado @@ -101,6 +105,7 @@ copy_url=Copiar URL copy_hash=Copiar hash copy_content=Copiar conteúdo copy_branch=Copiar nome do branch +copy_path=Copiar caminho copy_success=Copiado! copy_error=A cópia falhou copy_type_unsupported=Este tipo de arquivo não pode ser copiado @@ -108,10 +113,14 @@ copy_type_unsupported=Este tipo de arquivo não pode ser copiado write=Escrever preview=Pré-visualização loading=Carregando… +files=Arquivos error=Erro error404=A página que você está tentando acessar não existe ou você não está autorizado a visualizá-la. +error503=O servidor foi incapaz de concluir sua solicitação. Por favor, tente novamente mais tarde. go_back=Voltar +invalid_data=Dados inválidos: %v +nothing_has_been_changed=Nada foi alterado. never=Nunca unknown=Desconhecido @@ -122,6 +131,8 @@ pin=Fixar unpin=Desfixar artifacts=Artefatos +expired=Expirado +confirm_delete_artifact=Tem certeza que deseja excluir o artefato '%s'? archived=Arquivado @@ -139,18 +150,53 @@ confirm_delete_selected=Confirma a exclusão de todos os itens selecionados? name=Nome value=Valor +readme=Readme filter=Filtro +filter.clear=Limpar Filtro filter.is_archived=Arquivado +filter.not_archived=Não Arquivados +filter.is_fork=Fork +filter.not_fork=Não Fork +filter.is_mirror=Espelhado +filter.not_mirror=Não espelhado filter.is_template=Template +filter.not_template=Não Modelo filter.public=Pública filter.private=Privado +no_results_found=Nenhum resultado encontrado. +internal_error_skipped=Ocorreu um erro interno, mas foi ignorado: %s [search] +search=Pesquisar… +type_tooltip=Tipo de pesquisa +fuzzy=Fuzzy +fuzzy_tooltip=Incluir resultados que sejam próximos ao termo de busca +words=Palavras +words_tooltip=Incluir somente resultados que correspondam às palavras do termo de busca +regexp=Regexp +regexp_tooltip=Incluir somente resultados que correspondam ao termo de pesquisa regexp +exact=Exato +exact_tooltip=Incluir somente resultados que correspondam exatamente ao termo de busca +repo_kind=Pesquisar repositório... +user_kind=Pesquisar usuário… +org_kind=Pesquisar orgs… +team_kind=Pesquisar equipes… +code_kind=Pesquisar código… +code_search_unavailable=A pesquisa por código está indisponível no momento. Entre em contato com o administrador. +package_kind=Pesquisar pacotes… +project_kind=Pesquisar projetos… +branch_kind=Pesquisar branches… +tag_kind=Pesquisar tags… +commit_kind=Pesquisar commits… +runner_kind=Pesquisar runners… +no_results=Nenhum resultado foi encontrado. +issue_kind=Pesquisar issues… +pull_kind=Pesquisar pull requests… [aria] -navbar=Barra de navegação +navbar=Barra de Navegação footer=Rodapé footer.software=Sobre o Software footer.links=Links @@ -171,7 +217,10 @@ buttons.link.tooltip=Adicionar um link buttons.list.unordered.tooltip=Adicionar uma lista com marcadores buttons.list.ordered.tooltip=Adicionar uma lista numerada buttons.list.task.tooltip=Adicionar uma lista de tarefas +buttons.table.add.tooltip=Adicionar uma tabela buttons.table.add.insert=Adicionar +buttons.table.rows=Linhas +buttons.table.cols=Colunas buttons.mention.tooltip=Mencionar um usuário ou equipe buttons.ref.tooltip=Referenciar um issue ou um pull request buttons.switch_to_legacy.tooltip=Em vez disso, usar o editor legado @@ -179,31 +228,37 @@ buttons.enable_monospace_font=Habilitar fonte mono espaçada buttons.disable_monospace_font=Desabilitar fonte mono espaçada [filter] +string.asc=A–Z +string.desc=Z–A [error] occurred=Ocorreu um erro +report_message=Se você acredita que esse é um falha do Gitea, pesquise por issues no GitHub ou abra uma nova issue, se necessário. not_found=Não foi possível encontrar o destino. network_error=Erro de rede [startpage] -app_desc=Um serviço de hospedagem Git amigável +app_desc=Um serviço amigável de Git selfhosted install=Fácil de instalar +install_desc=Simplesmente execute o binário para sua plataforma, suba com Docker, or use um pacote. platform=Multi-plataforma +platform_desc=Gitea roda em qualquer lugar para qual Go consegue compilar: Windows, macOS, Linux, ARM, etc. Escolha qual você gosta mais! lightweight=Leve e rápido -lightweight_desc=Gitea utiliza poucos recursos e consegue mesmo rodar no barato Raspberry Pi. Economize energia elétrica da sua máquina! -license=Código aberto +lightweight_desc=Gitea tem requisitos minimos e pode rodar até em um Raspberry Pi. Economize energia da sua máquina! +license=Código Aberto +license_desc=Receba %[2]s! Junte-se a nós contribuindo para tornar este projeto ainda melhor. Não seja tímido, seja um colaborador! [install] install=Instalação -title=Configuração inicial +title=Configuração Inicial docker_helper=Se você está rodando o Gitea dentro do Docker, por favor leia a documentação cuidadosamente antes de alterar qualquer coisa nesta página. require_db_desc=Gitea requer MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (protocolo MySQL). -db_title=Configurações de banco de dados -db_type=Tipo de banco de dados +db_title=Configurações de Banco de Dados +db_type=Tipo de Banco de Dados host=Servidor user=Nome de usuário password=Senha -db_name=Nome do banco de dados +db_name=Nome do Banco de Dados db_schema=Esquema db_schema_helper=Deixe em branco para banco de dados padrão ("public"). ssl_mode=SSL @@ -211,64 +266,72 @@ path=Caminho sqlite_helper=Caminho do arquivo do banco de dados SQLite3.
Informe um caminho absoluto se você executar o Gitea como um serviço. reinstall_error=Você está tentando instalar em um banco de dados existente do Gitea reinstall_confirm_message=Reinstalar com um banco de dados Gitea existente pode causar vários problemas. Na maioria dos casos, você deve usar seu "app.ini" existente para executar o Gitea. Se você sabe o que está fazendo, confirme o seguinte: +reinstall_confirm_check_1=Os dados criptografados pelo SECRET_KEY no app.ini poderão ser perdidos: os usuários podem não conseguir fazer login com 2FA/OTP e espelhos podem não funcionar corretamente. Ao marcar esta caixa você confirma que o atual arquivo app.ini contém o SECRET_KEY correto. +reinstall_confirm_check_2=Os repositórios e configurações podem precisar ser re-sincronizados. Marcando esta caixa você confirma que irá sincronizar novamente os hooks para os repositórios e o arquivo authorized_keys manualmente. Você confirma que irá garantir que as configurações de repositório e espelhamento estão corretas. reinstall_confirm_check_3=Você confirma que este Gitea está realmente executando com a localização correta do app.ini e que você tem certeza de que precisa reinstalar. Você confirma que tomou conhecimento dos riscos acima descritos. err_empty_db_path=O caminho do banco de dados SQLite3 não pode ser em branco. no_admin_and_disable_registration=Você não pode desabilitar o auto-cadastro do usuário sem criar uma conta de administrador. err_empty_admin_password=A senha do administrador não pode ser em branco. +err_empty_admin_email=O e-mail do administrador não pode estar em branco. +err_admin_name_is_reserved=Nome de usuário do administrador é inválido, nome de usuário está reservado. +err_admin_name_pattern_not_allowed=Nome de usuário administrador é inválido. O nome de usuário corresponde a um padrão reservado. +err_admin_name_is_invalid=Nome de usuário do administrador inválido -general_title=Configurações gerais -app_name=Nome do servidor +general_title=Configurações Gerais +app_name=Nome do Site app_name_helper=Você pode inserir o nome da empresa aqui. -repo_path=Caminho raíz do repositório +repo_path=Caminho Raíz do Repositório repo_path_helper=Todos os repositórios remotos do Git serão salvos neste diretório. lfs_path=Caminho raiz do Git LFS lfs_path_helper=Os arquivos armazenados com o Git LFS serão armazenados neste diretório. Deixe em branco para desabilitar. -run_user=Executar como nome de usuário +run_user=Executar como Usuário run_user_helper=O nome de usuário do sistema operacional com o qual o Gitea é executado. Observe que este usuário deve ter acesso ao caminho da raiz do repositório. -domain=Domínio do servidor +domain=Domínio do Servidor domain_helper=Domínio ou endereço de host para o servidor. ssh_port=Porta do servidor SSH ssh_port_helper=Número da porta que seu servidor SSH está usando. Deixe em branco para desabilitar. http_port=Porta HTTP de uso do Gitea +http_port_helper=Número da porta que o servidor web do Gitea irá usar. app_url=URL base do Gitea app_url_helper=Endereço base para URLs clone HTTP(S) e notificações por e-mail. -log_root_path=Caminho do log +log_root_path=Caminho do Log log_root_path_helper=Arquivos de log serão gravados neste diretório. -optional_title=Configurações opcionais -email_title=Configurações de e-mail +optional_title=Configurações Opcionais +email_title=Configurações de E-mail smtp_addr=Host SMTP smtp_port=Porta SMTP -smtp_from=Enviar e-mail como +smtp_from=Enviar E-mail Como +smtp_from_invalid=O endereço "Enviar e-mail como" é inválido smtp_from_helper=Endereço de e-mail que o Gitea irá usar. Digite um endereço de e-mail simples ou use o formato "Nome" . mailer_user=Nome de usuário do SMTP mailer_password=Senha do SMTP -register_confirm=Exigir confirmação de e-mail para se cadastrar -mail_notify=Habilitar notificações de e-mail -server_service_title=Configurações de servidor e serviços de terceiros -offline_mode=Habilitar autenticação local +register_confirm=Exigir Confirmação de E-mail para se Cadastrar +mail_notify=Habilitar Notificações de E-mail +server_service_title=Configurações de Servidor e Serviços de Terceiros +offline_mode=Habilitar Autenticação Local offline_mode_popup=Desabilitar redes de entrega de conteúdo de terceiros e entregar todos os recursos localmente. -disable_gravatar=Desabilitar o gravatar +disable_gravatar=Desabilitar o Gravatar disable_gravatar_popup=Desabilitar o gravatar e avatar de fontes de terceiros. Um avatar padrão será usado a menos que um usuário localmente carrega um avatar. -federated_avatar_lookup=Habilitar avatares federativos +federated_avatar_lookup=Habilitar Avatares Federativos federated_avatar_lookup_popup=Habilitar a busca federativa de avatares a usar o serviço federativo de código aberto baseado no libravatar. -disable_registration=Desabilitar auto-cadastro +disable_registration=Desabilitar Auto-Cadastro disable_registration_popup=Desabilitar auto-cadastro de usuário. Somente os administradores serão capazes de criar novas contas de usuário. -allow_only_external_registration_popup=Permitir cadastro somente por meio de serviços externos +allow_only_external_registration_popup=Permitir Cadastro Somente por Meio de Serviços Externos openid_signin=Habilitar acesso via OpenID openid_signin_popup=Habilitar o acesso de usuários via OpenID. openid_signup=Habilitar o auto-cadastro via OpenID openid_signup_popup=Habilitar o auto-cadastro com base no OpenID. enable_captcha=Habilitar CAPTCHA ao registrar enable_captcha_popup=Obrigar validação por CAPTCHA para auto-cadastro de usuários. -require_sign_in_view=Exigir acesso do usuário para a visualização de páginas +require_sign_in_view=Exigir Acesso para a Visualização de Páginas require_sign_in_view_popup=Limitar o acesso de página aos usuários autenticados. Os visitantes só verão as páginas de autenticação e cadastro. admin_setting_desc=Criar uma conta de administrador é opcional. O primeiro usuário cadastrado automaticamente se tornará um administrador. -admin_title=Configurações da conta de administrador -admin_name=Nome do usuário administrador +admin_title=Configurações da Conta de Administrador +admin_name=Nome do Usuário Administrador admin_password=Senha -confirm_password=Confirmar senha -admin_email=Endereço de e-mail +confirm_password=Confirmar Senha +admin_email=Endereço de E-mail install_btn_confirm=Instalar Gitea test_git_failed=Falha ao testar o comando 'git': %v sqlite3_not_available=Esta versão do Gitea não suporta SQLite3. Por favor faça o download da versão binária oficial em %s (não utilize a versão 'gobuild'). @@ -282,32 +345,35 @@ secret_key_failed=Falha ao gerar a chave secreta: %v save_config_failed=Falha ao salvar a configuração: %v invalid_admin_setting=Configuração da conta de administrador está inválida: %v invalid_log_root_path=Pasta raíz do log está inválida: %v -default_keep_email_private=Ocultar endereços de e-mail por padrão +default_keep_email_private=Ocultar Endereços de E-mail por Padrão default_keep_email_private_popup=Ocultar endereços de e-mail de novas contas de usuário por padrão. -default_allow_create_organization=Permitir a criação de organizações por padrão +default_allow_create_organization=Permitir a Criação de Organizações por Padrão default_allow_create_organization_popup=Permitir que novas contas de usuários criem organizações por padrão. default_enable_timetracking=Habilitar o Cronômetro por Padrão default_enable_timetracking_popup=Habilitar o cronômetro para novos repositórios por padrão. -no_reply_address=Domínio de e-mail oculto +no_reply_address=Domínio de E-mail Oculto no_reply_address_helper=Nome de domínio para usuários com um endereço de e-mail oculto. Por exemplo, o nome de usuário 'joe' será registrado no Git como 'joe@noreply.example.org' se o domínio de e-mail oculto estiver definido como 'noreply.example.org'. password_algorithm=Algoritmo Hash de Senha invalid_password_algorithm=Algoritmo de hash de senha inválido +password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O algoritmo argon2 é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas com menos recursos. enable_update_checker=Habilitar Verificador de Atualizações enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io. -env_config_keys=Configuração do ambiente +env_config_keys=Configuração do Ambiente env_config_keys_prompt=As seguintes variáveis de ambiente também serão aplicadas ao seu arquivo de configuração: +config_write_file_prompt=Estas opções de configuração serão escritas em: %s [home] -uname_holder=Usuário ou e-mail +nav_menu=Menu de Navegação +uname_holder=Usuário ou E-mail password_holder=Senha -switch_dashboard_context=Trocar contexto do painel de controle +switch_dashboard_context=Trocar Contexto do Painel de Controle my_repos=Repositórios show_more_repos=Mostrar mais repositórios… -collaborative_repos=Repositórios colaborativos -my_orgs=Minhas organizações -my_mirrors=Meus espelhos +collaborative_repos=Repositórios Colaborativos +my_orgs=Minhas Organizações +my_mirrors=Meus Espelhos view_home=Ver %s -filter=Outros filtros +filter=Outros Filtros filter_by_team_repositories=Filtrar por repositórios da equipe feed_of=`Feed de "%s"` @@ -323,6 +389,11 @@ show_only_public=Mostrando somente públicos issues.in_your_repos=Em seus repositórios +guide_title=Nenhuma Atividade +explore_repos=Explorar repositórios +explore_users=Explorar usuários +empty_org=Ainda não existem organizações. +empty_repo=Ainda não existem repositórios. [explore] repos=Repositórios @@ -335,30 +406,38 @@ relevant_repositories_tooltip=Repositórios que são forks ou que não possuem t relevant_repositories=Apenas repositórios relevantes estão sendo mostrados, mostrar resultados não filtrados. [auth] -create_new_account=Cadastrar conta +create_new_account=Cadastrar Conta +already_have_account=Já tem uma conta? +sign_in_now=Entre agora! disable_register_prompt=Cadastro está desabilitado. Entre em contato com o administrador do site. disable_register_mail=E-mail de confirmação de cadastro está desabilitado. manual_activation_only=Entre em contato com o administrador do site para concluir a ativação. remember_me=Lembrar deste Dispositivo remember_me.compromised=O token de login não é mais válido, o que pode indicar uma conta comprometida. Por favor, verifique a sua conta por atividades incomuns. -forgot_password_title=Esqueci minha senha +forgot_password_title=Esqueci a Senha forgot_password=Esqueceu sua senha? +need_account=Precisa de uma conta? +sign_up_now=Cadastre-se agora. sign_up_successful=A conta foi criada com sucesso. Bem-vindo! +confirmation_mail_sent_prompt_ex=Um novo e-mail de confirmação foi enviado para %s. Por favor, verifique sua caixa de entrada dentro dos próximos %s para concluir o processo de registro. Se o seu endereço de e-mail de registro estiver incorreto, você pode fazer login novamente e alterá-lo. must_change_password=Redefina sua senha allow_password_change=Exigir que o usuário redefina a senha (recomendado) reset_password_mail_sent_prompt=Um e-mail de confirmação foi enviado para %s. Por favor, verifique sua caixa de entrada dentro do(s) próximo(s) %s para concluir o processo de recuperação de conta. -active_your_account=Ativar sua conta +active_your_account=Ativar sua Conta account_activated=Conta foi ativada +prohibit_login=Acesso Proibido +prohibit_login_desc=Sua conta está proibida de fazer login, entre em contato com o administrador do site. resent_limit_prompt=Você já solicitou recentemente um e-mail de ativação. Por favor, aguarde 3 minutos e tente novamente. has_unconfirmed_mail=Oi %s, você possui um endereço de e-mail não confirmado (%s). Se você não recebeu um e-mail de confirmação ou precisa reenviar um novo, clique no botão abaixo. +change_unconfirmed_mail_address=Se o seu endereço de e-mail de registro estiver incorreto, você pode mudá-lo aqui e reenviar um novo e-mail de confirmação. resend_mail=Clique aqui para reenviar seu e-mail de ativação email_not_associate=O endereço de e-mail não está associado à nenhuma conta. -send_reset_mail=Enviar e-mail de recuperação de conta -reset_password=Recuperação de conta +send_reset_mail=Enviar E-mail de Recuperação de Conta +reset_password=Recuperação de Conta invalid_code=Seu código de confirmação é inválido ou expirou. invalid_code_forgot_password=Seu código de confirmação expirou ou está inválido. Clique aqui para iniciar uma nova sessão. invalid_password=Sua senha não coincide com a senha que foi usada para criar a conta. -reset_password_helper=Recuperar conta +reset_password_helper=Recuperar Conta reset_password_wrong_user=Você está conectado como %s, mas o link de recuperação de conta é destinado a %s password_too_short=A senha deve ter %d ou mais caracteres. non_local_account=Usuários não-locais não podem atualizar sua senha através da interface web do Gitea. @@ -370,12 +449,12 @@ twofa_passcode_incorrect=Seu código de acesso está incorreto. Se você perdeu twofa_scratch_token_incorrect=Seu código de backup está incorreto. login_userpass=Acessar login_openid=OpenID -oauth_signup_tab=Cadastrar nova conta +oauth_signup_tab=Cadastrar Nova Conta oauth_signup_title=Completar Nova Conta -oauth_signup_submit=Completar conta +oauth_signup_submit=Completar Conta oauth_signin_tab=Vincular à uma conta existente -oauth_signin_title=Acesse com uma conta vinculada -oauth_signin_submit=Vincular conta +oauth_signin_title=Acesse para Autorizar Conta Vinculada +oauth_signin_submit=Vincular Conta oauth.signin.error.access_denied=O pedido de autorização foi negado. oauth.signin.error.temporarily_unavailable=A autorização falhou porque o servidor de autenticação está temporariamente indisponível. Por favor, tente novamente mais tarde. openid_connect_submit=Conectar @@ -384,15 +463,21 @@ openid_connect_desc=O URI do OpenID escolhido é desconhecido. Associe-o com uma openid_register_title=Criar uma nova conta openid_register_desc=O URI do OpenID escolhido é desconhecido. Associe-o com uma nova conta aqui. openid_signin_desc=Digite o URI do seu OpenID. Por exemplo: alice.openid.example.org ou https://openid.example.org/alice. +disable_forgot_password_mail=A recuperação de conta está desativada porque nenhum e-mail está configurado. Por favor, contate o administrador do site. +disable_forgot_password_mail_admin=A recuperação de conta só está disponível quando o e-mail está configurado. email_domain_blacklisted=Você não pode se cadastrar com seu endereço de e-mail. -authorize_application=Autorizar aplicativo +authorize_application=Autorizar Aplicativo authorize_redirect_notice=Você será redirecionado para %s se você autorizar este aplicativo. authorize_application_created_by=Este aplicativo foi criado por %s. +authorize_application_description=Se você conceder o acesso, ele será capaz de acessar e escrever em todas as informações da sua conta, incluindo repositórios privados e organizações. authorize_title=Autorizar "%s" para acessar sua conta? authorization_failed=Autorização falhou +authorization_failed_desc=A autorização falhou porque detectamos uma solicitação inválida. Entre em contato com o responsável do aplicativo que você tentou autorizar. sspi_auth_failed=Falha de autenticação SSPI +password_pwned=A senha que você escolheu faz parte de uma lista de senhas roubadas expostas anteriormente em violações de dados. Tente novamente com uma senha diferente e considere alterar a senha em outros lugares. password_pwned_err=Não foi possível concluir a requisição ao HaveIBeenPwned last_admin=Você não pode remover o último administrador. Deve haver pelo menos um administrador. +back_to_sign_in=Voltar ao Login [mail] view_it_on=Veja em %s @@ -409,7 +494,10 @@ activate_email=Verifique seu endereço de e-mail activate_email.title=%s, por favor verifique o seu endereço de e-mail activate_email.text=Por favor clique no link a seguir para verificar o seu endereço de e-mail em %s: +register_notify=Bem-vindo ao %s register_notify.title=%[1]s, bem-vindo(a) a %[2]s +register_notify.text_1=Este é o seu e-mail de confirmação de registro para %s! +register_notify.text_2=Agora você pode entrar com o nome de usuário: %s. register_notify.text_3=Se esta conta foi criada para você, defina sua senha primeiro. reset_password=Recuperar sua conta @@ -441,12 +529,13 @@ release.new.text=@%[1]s lançou a versão %[2]s em %[3]s release.title=Título: %s release.note=Nota: release.downloads=Downloads: -release.download.zip=Código fonte (ZIP) -release.download.targz=Código fonte (TAR.GZ) +release.download.zip=Código Fonte (ZIP) +release.download.targz=Código Fonte (TAR.GZ) repo.transfer.subject_to=%s gostaria de transferir "%s" para %s repo.transfer.subject_to_you=%s gostaria de transferir "%s" para você repo.transfer.to_you=você +repo.transfer.body=Para o aceitar ou rejeitar visite %s, ou simplesmente o ignore. repo.collaborator.added.subject=%s adicionou você a %s repo.collaborator.added.text=Você foi adicionado como um colaborador do repositório: @@ -468,7 +557,7 @@ UserName=Nome de usuário RepoName=Nome do repositório Email=Endereço de e-mail Password=Senha -Retype=Confirmar senha +Retype=Confirmar Senha SSHTitle=Nome da chave SSH HttpsUrl=URL HTTPS PayloadUrl=URL de carga @@ -484,7 +573,7 @@ TreeName=Caminho do arquivo Content=Conteúdo SSPISeparatorReplacement=Separador -SSPIDefaultLanguage=Idioma padrão +SSPIDefaultLanguage=Idioma Padrão require_error=` não pode estar em branco.` alpha_dash_error=` deve conter somente alfanumérico, caracteres de traço ('-') e sublinhado ('_').` @@ -498,6 +587,7 @@ url_error= `"%s" não é um URL válido.` include_error=` deve conter "%s".` glob_pattern_error=` padrão glob é inválido: %s.` regex_pattern_error=` o regex é inválido: %s.` +username_error=` só pode conter caracteres alfanuméricos ('0-9','a-z','A-Z'), traço ('-'), sublinhado ('_') e ponto ('.'). Não pode começar ou terminar com caracteres não alfanuméricos, e caracteres não-alfanuméricos consecutivos também são proibidos.` invalid_group_team_map_error=` mapeamento é inválido: %s` unknown_error=Erro desconhecido: captcha_incorrect=O código CAPTCHA está incorreto. @@ -506,18 +596,23 @@ lang_select_error=Selecione um idioma da lista. username_been_taken=O nome de usuário já está sendo usado. username_change_not_local_user=Usuários não-locais não são autorizados a alterar nome de usuário. +change_username_disabled=Alterar nome de usuário está desabilitado. +change_full_name_disabled=Alterar nome completo está desabilitado. username_has_not_been_changed=Nome de usuário não foi alterado repo_name_been_taken=O nome de repositório já está sendo usado. repository_force_private=Forçar Privado está ativado: repositórios privados não podem ser tornados públicos. repository_files_already_exist=Arquivos já existem neste repositório. Contate o administrador. +repository_files_already_exist.adopt=Arquivos já existem neste repositório e só podem ser adotados. repository_files_already_exist.delete=Arquivos já existem neste repositório. Você deve deletá-los. repository_files_already_exist.adopt_or_delete=Arquivos já existem neste repositório. Você deve adotá-los ou deletá-los. visit_rate_limit=Limitação da taxa de visita remota. +2fa_auth_required=Visita remota requer autenticação de dois fatores. org_name_been_taken=O nome da organização já está sendo usado. team_name_been_taken=O nome da equipe já está sendo usado. team_no_units_error=Permitir acesso a pelo menos uma seção de repositório. email_been_used=Este endereço de e-mail já está sendo usado. email_invalid=O endereço de email é inválido. +email_domain_is_not_allowed=O domínio do e-mail do usuário %s conflita com EMAIL_DOMAIN_ALLOWLIST ou EMAIL_DOMAIN_BLOCKLIST. Por favor, certifique-se de que a sua operação é esperada. openid_been_used=O endereço OpenID "%s" já está sendo usado. username_password_incorrect=Nome de usuário ou senha incorretos. password_complexity=A senha não passa pelos requisitos de complexidade: @@ -529,6 +624,8 @@ enterred_invalid_repo_name=O nome do repositório que você digitou está incorr enterred_invalid_org_name=O nome da organização inserido é incorreto. enterred_invalid_owner_name=O nome do novo proprietário não é válido. enterred_invalid_password=A senha que você digitou está incorreta. +unset_password=O usuário de login não definiu a senha. +unsupported_login_type=O tipo de login não é suportado para excluir a conta. user_not_exist=O usuário não existe. team_not_exist=A equipe não existe. last_org_owner=Você não pode remover o último usuário do time 'proprietários'. Deve haver pelo menos um proprietário em uma organização. @@ -540,10 +637,17 @@ invalid_ssh_key=Não é possível verificar sua chave SSH: %s invalid_gpg_key=Não é possível verificar sua chave GPG: %s invalid_ssh_principal=Nome principal inválido: %s must_use_public_key=A chave que você forneceu é uma chave privada. Por favor, não envie sua chave privada em nenhum lugar. Use sua chave pública em vez disso. +unable_verify_ssh_key=Não é possível verificar a chave SSH, verifique se há erros. auth_failed=Autenticação falhou: %v +still_own_repo=Sua conta possui um ou mais repositórios, exclua ou transfira-os primeiro. +still_has_org=Sua conta é um membro de uma ou mais organizações, deixe-as primeiro. +still_own_packages=Sua conta possui um ou mais pacotes, exclua-os primeiro. +org_still_own_repo=Esta organização ainda possui repositórios, exclua ou transfira-os primeiro. +org_still_own_packages=Esta organização ainda possui pacotes, exclua-os primeiro. target_branch_not_exist=O branch de destino não existe. +target_ref_not_exist=Ref de destino não existe %s admin_cannot_delete_self=Você não pode excluir você mesmo quando você é um administrador. Por favor, remova seus privilégios de administrador primeiro. @@ -551,11 +655,11 @@ admin_cannot_delete_self=Você não pode excluir você mesmo quando você é um change_avatar=Altere seu avatar... joined_on=Inscreveu-se em %s repositories=Repositórios -activity=Atividade pública +activity=Atividade Pública followers=Seguidores -show_more=Mostrar mais -starred=Repositórios favoritos -watched=Repositórios observados +show_more=Mostrar Mais +starred=Repositórios Favoritos +watched=Repositórios Observados code=Código projects=Projetos overview=Visão geral @@ -567,11 +671,28 @@ disabled_public_activity=Este usuário desativou a visibilidade pública da ativ email_visibility.limited=Seu endereço de e-mail está visível para todos os usuários autenticados email_visibility.private=Seu endereço de e-mail é visível apenas para você e administradores show_on_map=Mostrar este lugar em um mapa -settings=Configurações do usuário +settings=Configurações do Usuário form.name_reserved=O nome de usuário "%s" está reservado. form.name_pattern_not_allowed=O padrão de "%s" não é permitido em um nome de usuário. +form.name_chars_not_allowed=Nome de usuário "%s" contém caracteres inválidos. +block.block=Bloquear +block.block.user=Bloquear usuário +block.block.org=Bloquear usuário para organização +block.block.failure=Falha ao bloquear usuário: %s +block.unblock=Desbloquear +block.unblock.failure=Falha ao desbloquear o usuário: %s +block.blocked=Você bloqueou este usuário. +block.title=Bloquear um usuário +block.info_2=seguindo sua conta +block.user_to_block=Usuário a bloquear +block.note=Nota +block.note.title=Nota opcional: +block.note.info=A nota não é visível para o usuário bloqueado. +block.note.edit=Editar nota +block.list=Usuários bloqueados +block.list.none=Você não bloqueou nenhum usuário. [settings] profile=Perfil @@ -581,23 +702,27 @@ password=Senha security=Segurança avatar=Avatar ssh_gpg_keys=Chaves SSH / GPG -social=Contas sociais +social=Contas Sociais applications=Aplicativos -orgs=Gerenciar organizações +orgs=Gerenciar Organizações repos=Repositórios -delete=Excluir conta -account_link=Contas vinculadas +delete=Excluir Conta +twofa=Autenticação de Dois Fatores (TOTP) +account_link=Contas Vinculadas organization=Organizações uid=UID +webauthn=Autenticação de Dois Fatores (Chaves de Segurança) -public_profile=Perfil público +public_profile=Perfil Público biography_placeholder=Conte-nos um pouco sobre você! (Você pode usar Markdown) location_placeholder=Compartilhe sua localização aproximada com outras pessoas -full_name=Nome completo +profile_desc=Controle como o seu perfil é exibido para outros usuários. Seu endereço de e-mail principal será usado para notificações, recuperação de senha e operações do Git baseadas na Web. +password_username_disabled=Você não tem permissão para mudar seu nome de usuário. Entre em contato com o administrador do site para mais detalhes. +full_name=Nome Completo website=Site location=Localização -update_theme=Atualizar o tema -update_profile=Atualizar o perfil +update_theme=Atualizar o Tema +update_profile=Atualizar o Perfil update_language=Atualizar Idioma update_language_not_found=Idioma "%s" não está disponível. update_language_success=O idioma foi atualizado. @@ -610,6 +735,7 @@ cancel=Cancelar language=Idioma ui=Tema hidden_comment_types=Tipos de comentários ocultos +hidden_comment_types_description=Tipos de comentários marcados aqui não serão mostrados nas páginas de issues. Marcar "Etiqueta", por exemplo, remove todos os comentários "{usuário} adicionou/removeu {etiqueta}". hidden_comment_types.ref_tooltip=Comentários onde este issue foi referenciado de outro issue/commit/… hidden_comment_types.issue_ref_tooltip=Comentários onde o usuário altera o branch/tag associado ao issue comment_type_group_reference=Referência @@ -618,7 +744,7 @@ comment_type_group_milestone=Marco comment_type_group_assignee=Atribuído comment_type_group_title=Título comment_type_group_branch=Branch -comment_type_group_time_tracking=Contador de tempo +comment_type_group_time_tracking=Cronômetro comment_type_group_deadline=Prazo final comment_type_group_dependency=Dependência comment_type_group_lock=Status de Bloqueio @@ -628,30 +754,30 @@ comment_type_group_project=Projeto comment_type_group_issue_ref=Referência do issue saved_successfully=Suas configurações foram salvas com sucesso. privacy=Privacidade -keep_activity_private=Ocultar atividade da página de perfil +keep_activity_private=Ocultar Atividade da Página de Perfil keep_activity_private_popup=Torna a atividade visível somente para você e os administradores -lookup_avatar_by_mail=Procurar o avatar do endereço de e-mail -federated_avatar_lookup=Busca de avatar federativo -enable_custom_avatar=Habilitar avatar customizado +lookup_avatar_by_mail=Procurar o Avatar do Endereço de E-mail +federated_avatar_lookup=Busca de Avatar Federativo +enable_custom_avatar=Usar Avatar Customizado choose_new_avatar=Escolha um novo avatar -update_avatar=Atualizar o avatar -delete_current_avatar=Excluir o avatar atual +update_avatar=Atualizar o Avatar +delete_current_avatar=Excluir o Avatar Atual uploaded_avatar_not_a_image=O arquivo enviado não é uma imagem. uploaded_avatar_is_too_big=O tamanho do arquivo enviado (%d KiB) excede o tamanho máximo permitido (%d KiB). update_avatar_success=Seu avatar foi atualizado. update_user_avatar_success=O avatar do usuário foi atualizado. -change_password=Atualizar senha -old_password=Senha atual -new_password=Nova senha -retype_new_password=Confirmar nova senha +change_password=Atualizar Senha +old_password=Senha Atual +new_password=Nova Senha +retype_new_password=Confirmar Nova Senha password_incorrect=A senha atual está incorreta. change_password_success=Sua senha foi atualizada. Acesse usando sua nova senha de agora em diante. password_change_disabled=Contas não-locais não podem alterar sua senha através da interface web do Gitea. -emails=Endereços de e-mail -manage_emails=Gerenciar endereços de e-mail +emails=Endereços de E-mail +manage_emails=Gerenciar Endereços de E-mail manage_themes=Selecione o tema padrão manage_openid=Gerencia endereços OpenID email_desc=Seu endereço de e-mail principal será usado para notificações, recuperação de senha e, desde que não esteja oculto, para operações do Git baseadas na Web. @@ -661,31 +787,33 @@ activated=Ativado requires_activation=Requer ativação primary_email=Tornar Principal activate_email=Enviar Ativação -activations_pending=Ativações pendentes +activations_pending=Ativações Pendentes +can_not_add_email_activations_pending=Há uma ativação pendente, tente novamente em alguns minutos se quiser adicionar um novo e-mail. delete_email=Remover -email_deletion=Remover endereço de e-mail +email_deletion=Remover Endereço de E-mail +email_deletion_desc=Este endereço de e-mail e informações relacionadas serão removidos de sua conta. Commits aplicados por este endereço de e-mail permanecerão inalterados. Continuar? email_deletion_success=O endereço de e-mail foi removido. theme_update_success=Seu tema foi atualizado. theme_update_error=O tema selecionado não existe. openid_deletion=Remover endereço de OpenID openid_deletion_desc=A exclusão deste endereço OpenID da sua conta impedirá que você acesse com ele. Continuar? openid_deletion_success=O endereço de OpenID foi removido. -add_new_email=Adicionar novo endereço de e-mail +add_new_email=Adicionar Novo Endereço de E-mail add_new_openid=Adicionar novo URI OpenID -add_email=Adicionar novo endereço de e-mail +add_email=Adicionar Endereço de E-mail add_openid=Adicionar URI OpenID add_email_confirmation_sent=Um e-mail de confirmação foi enviado para "%s". Verifique sua caixa de entrada nos próximos %s para confirmar seu endereço de e-mail. add_email_success=O novo endereço de e-mail foi adicionado. email_preference_set_success=Preferência de e-mail definida com sucesso. add_openid_success=O novo endereço de OpenID foi adicionado. -keep_email_private=Ocultar endereço de e-mail +keep_email_private=Ocultar Endereço de E-mail keep_email_private_popup=Isso ocultará seu endereço de e-mail do seu perfil, bem como quando você fizer um pull request ou editar um arquivo usando a interface Web. Os commits enviados não serão modificados. openid_desc=OpenID permite delegar autenticação para um provedor externo. manage_ssh_keys=Gerenciar Chaves SSH manage_ssh_principals=Gerenciar Nomes Principais do certificado SSH manage_gpg_keys=Gerenciar chaves GPG -add_key=Adicionar chave +add_key=Adicionar Chave ssh_desc=Estas chaves SSH públicas estão associados a sua conta. Chaves privadas correspondentes permitam acesso completo a seus repositórios. principal_desc=Estes nomes principais do certificado SSH estão associados à sua conta e permitem acesso total aos seus repositórios. gpg_desc=Essas chaves GPG públicas estão associadas à sua conta. Mantenha suas chaves privadas seguras, pois elas permitem que os commits sejam verificados. @@ -701,20 +829,22 @@ ssh_key_name_used=Uma chave SSH com o mesmo nome já existe em sua conta. ssh_principal_been_used=Este nome principal já foi adicionada ao servidor. gpg_key_id_used=Uma chave GPG pública com a mesma ID já existe. gpg_no_key_email_found=Esta chave GPG não corresponde a nenhum endereço de e-mail ativado associado à sua conta. Ela ainda pode ser adicionada se você assinar o token fornecido. -gpg_key_matched_identities=Identidades correspondentes: +gpg_key_matched_identities=Identidades Correspondentes: gpg_key_matched_identities_long=As identidades incorporadas nesta chave coincidem com os seguintes endereços de email ativados para este usuário. Os commits correspondentes a estes endereços de e-mail podem ser verificados com esta chave. -gpg_key_verified=Chave validada +gpg_key_verified=Chave Validada gpg_key_verified_long=A chave foi validada com um token e pode ser usada para verificar commits correspondentes a qualquer endereço de e-mail ativado para esse usuário, além de quaisquer identidades correspondentes para essa chave. gpg_key_verify=Validar +gpg_invalid_token_signature=A chave GPG fornecida, a assinatura e o token não correspondem ou então o token expirou. gpg_token_required=Você tem que fornecer uma assinatura para o token abaixo gpg_token=Token gpg_token_help=Você pode gerar uma assinatura usando: gpg_token_signature=Assinatura GPG blindada key_signature_gpg_placeholder=Começa com '-----BEGIN PGP SIGNATURE-----' verify_gpg_key_success=A chave GPG "%s" foi validada. -ssh_key_verified=Chave validada +ssh_key_verified=Chave Validada ssh_key_verified_long=A chave foi validada com um token e pode ser usada para validar commits que correspondam a qualquer dos endereços de e-mail ativados deste usuário. ssh_key_verify=Validar +ssh_invalid_token_signature=A chave, assinatura ou token SSH fornecidos não coincidem, ou então o token expirou. ssh_token_required=Você tem que fornecer uma assinatura para o token abaixo ssh_token=Token ssh_token_help=Você pode gerar uma assinatura usando: @@ -722,7 +852,7 @@ ssh_token_signature=Assinatura SSH blindada key_signature_ssh_placeholder=Começa com '-----BEGIN SSH SIGNATURE-----' verify_ssh_key_success=A chave SSH "%s" foi validada. subkeys=Subchaves -key_id=ID da chave +key_id=ID da Chave key_name=Nome da Chave key_content=Conteúdo principal_content=Conteúdo @@ -735,6 +865,7 @@ gpg_key_deletion=Remover a chave GPG ssh_principal_deletion=Remover Nome Principal do Certificado SSH ssh_key_deletion_desc=A exclusão de uma chave SSH revoga seu acesso à sua conta. Continuar? gpg_key_deletion_desc=A exclusão de uma chave GPG cancela a verificação de confirmações assinadas por ela. Continuar? +ssh_principal_deletion_desc=A remoção de um Certificado de SSH Principal revoga seu acesso à sua conta. Continuar? ssh_key_deletion_success=A chave SSH foi removida. gpg_key_deletion_success=A chave GPG foi removida. ssh_principal_deletion_success=O nome principal foi removido. @@ -750,23 +881,23 @@ token_state_desc=Este token tem sido utilizado nos últimos 7 dias principal_state_desc=Este nome principal foi utilizado nos últimos 7 dias show_openid=Mostrar no perfil hide_openid=Ocultar no perfil -ssh_disabled=SSH desabilitado +ssh_disabled=SSH Desabilitado ssh_signonly=O SSH está desativado no momento, portanto, essas chaves são usadas apenas para verificação de assinatura de confirmação. ssh_externally_managed=Esta chave SSH para este usuário é gerenciada externamente -manage_social=Gerenciar contas sociais associadas +manage_social=Gerenciar Contas Sociais Associadas social_desc=Essas contas sociais podem ser usadas para fazer login em sua conta. Certifique-se de reconhecer todas elas. unbind=Desvincular unbind_success=A conta social foi removida com sucesso. -manage_access_token=Gerenciar tokens de acesso -generate_new_token=Gerar novo token +manage_access_token=Gerenciar Tokens de Acesso +generate_new_token=Gerar Novo Token tokens_desc=Esses tokens concedem acesso à sua conta usando a API do Gitea. -token_name=Nome do token -generate_token=Gerar token +token_name=Nome do Token +generate_token=Gerar Token generate_token_success=Seu novo token foi gerado. Copie-o agora, pois ele não será mostrado novamente. generate_token_name_duplicate=%s já foi usado como um nome de aplicativo. Por favor, use outro. delete_token=Excluir -access_token_deletion=Excluir token de acesso +access_token_deletion=Excluir Token de Acesso access_token_deletion_cancel_action=Cancelar access_token_deletion_confirm_action=Excluir access_token_deletion_desc=A exclusão de um token revoga o acesso à sua conta para aplicativos que o usam. Continuar? @@ -774,9 +905,11 @@ delete_token_success=O token foi excluído. Os aplicativos que o utilizam já n repo_and_org_access=Acesso ao Repositório e Organização permissions_public_only=Apenas público permissions_access_all=Todos (público, privado e limitado) -permission_no_access=Sem acesso +permission_not_set=Não definido +permission_no_access=Sem Acesso permission_read=Ler -permission_write=Ler e escrever +permission_write=Ler e Escrever +access_token_desc=As permissões de token selecionadas limitam a autorização somente às rotas da API correspondente. Leia a documentação para obter mais informações. at_least_one_permission=Você deve selecionar pelo menos uma permissão para criar um token permissions_list=Permissões: @@ -787,10 +920,11 @@ remove_oauth2_application=Remover aplicativo OAuth2 remove_oauth2_application_desc=Remover um aplicativo OAuth2 irá revogar o acesso a todos os tokens de acesso assinados. Continuar? remove_oauth2_application_success=O aplicativo foi excluído. create_oauth2_application=Criar um novo aplicativo OAuth2 -create_oauth2_application_button=Criar aplicativo +create_oauth2_application_button=Criar Aplicativo create_oauth2_application_success=Você criou um aplicativo OAuth2 com sucesso. update_oauth2_application_success=Você atualizou o aplicativo OAuth2 com sucesso. -oauth2_application_name=Nome do aplicativo +oauth2_application_name=Nome do Aplicativo +oauth2_confidential_client=Cliente Confidencial. Selecione para aplicativos que mantêm a confidencialidade do segredo, como aplicativos web. Não selecione para aplicativos nativos, incluindo aplicativos desktop e celulares. oauth2_redirect_uris=URIs de redirecionamento. Por favor use uma nova linha para cada URI. save_application=Salvar oauth2_client_id=Client ID @@ -804,33 +938,44 @@ oauth2_application_remove_description=A remoção de um aplicativo OAuth2 impedi oauth2_application_locked=O Gitea pré-registra alguns aplicativos OAuth2 na inicialização, se habilitados na configuração. Para evitar um comportamento inesperado, eles não podem ser editados nem removidos. Consulte a documentação do OAuth2 para obter mais informações. authorized_oauth2_applications=Aplicações OAuth2 autorizadas +authorized_oauth2_applications_description=Você concedeu acesso à sua conta pessoal da Gitea para esses aplicativos de terceiros. Revogue o acesso aos aplicativos de que não precisa mais. revoke_key=Revogar -revoke_oauth2_grant=Revogar acesso +revoke_oauth2_grant=Revogar Acesso +revoke_oauth2_grant_description=Revogar o acesso para este aplicativo de terceiros impedirá este aplicativo de acessar seus dados. Tem certeza? revoke_oauth2_grant_success=Acesso revogado com sucesso. +twofa_desc=Para proteger sua conta contra roubo de senhas, você pode usar um smartphone ou outro dispositivo para receber senhas únicas baseadas em tempo único ("TOTP"). twofa_recovery_tip=Se você perder o seu dispositivo, você será capaz de usar uma chave de recuperação de uso único para recuperar o acesso à sua conta. twofa_is_enrolled=Sua conta está atualmente habilitada com autenticação de dois fatores. -twofa_not_enrolled=Sua conta não está atualmente inscrita para a autenticação em duas etapas. -twofa_disable=Desabilitar a autenticação de dois fatores +twofa_not_enrolled=Sua conta não está usando autenticação em dois fatores. +twofa_disable=Desabilitar Autenticação de Dois Fatores +twofa_scratch_token_regenerate=Regenerar Chave de Recuperação de Uso-Único +twofa_scratch_token_regenerated=Sua chave de recuperação de uso único agora é %s. Armazene-a em um lugar seguro, pois não será mostrada novamente. +twofa_enroll=Habilitar Autenticação de Dois Fatores twofa_disable_note=Você pode desabilitar a autenticação de dois fatores se necessário. twofa_disable_desc=Desabilitar a autenticação de dois fatores tornará sua conta menos segura. Tem certeza que deseja continuar? +regenerate_scratch_token_desc=Se você perdeu o seu token de backup, ou teve que usá-lo para realizar um acesso, você pode redefini-lo. twofa_disabled=A autenticação de dois fatores foi desabilitada. scan_this_image=Escaneie esta imagem com o seu aplicativo de autenticação: or_enter_secret=Ou digite esse código: %s then_enter_passcode=E insira a senha mostrada no aplicativo: passcode_invalid=Esse código de acesso é inválido. Tente novamente. +twofa_enrolled=Sua conta foi habilitada com sucesso. Armazene sua chave de recuperação de uso único (%s) em um lugar seguro, pois ela não será exibida novamente. twofa_failed_get_secret=Falha ao obter o segredo. -webauthn_register_key=Adicionar chave de segurança +webauthn_desc=Chaves de segurança são dispositivos de hardware que contém chaves criptográficas. Elas podem ser usadas para autenticação de dois fatores. A chave de segurança deve suportar o padrão WebAuthn Authenticator. +webauthn_register_key=Adicionar Chave de Segurança webauthn_nickname=Apelido -webauthn_delete_key=Remover chave de segurança +webauthn_delete_key=Remover Chave de Segurança +webauthn_delete_key_desc=Se você remover uma chave de segurança, não poderá mais entrar usando ela. Continuar? webauthn_key_loss_warning=Se você perder suas chaves de segurança, perderá o acesso à sua conta. webauthn_alternative_tip=Você pode querer configurar um método de autenticação adicional. -manage_account_links=Gerenciar contas vinculadas +manage_account_links=Gerenciar Contas Vinculadas manage_account_links_desc=Estas contas externas estão vinculadas a sua conta de Gitea. +account_links_not_available=Nenhuma conta externa está conectada à sua conta de Gitea. link_account=Vincular Conta -remove_account_link=Remover conta vinculada +remove_account_link=Remover Conta Vinculada remove_account_link_desc=A exclusão da chave SSH revogará o acesso à sua conta. Continuar? remove_account_link_success=A conta vinculada foi removida. @@ -839,17 +984,17 @@ hooks.desc=Adicione webhooks que serão acionados para todos os reposit orgs_none=Você não é membro de nenhuma organização. repos_none=Você não é proprietário de nenhum repositório. -delete_account=Excluir sua conta +delete_account=Excluir Sua Conta delete_prompt=Esta operação irá apagar permanentemente a sua conta de usuário. Isto NÃO PODERÁ ser desfeito. delete_with_all_comments=Sua conta é mais nova que %s. Para evitar comentários fantasmas, todos os comentários de Issue/PR serão excluídos com ela. -confirm_delete_account=Confirmar exclusão -delete_account_title=Excluir conta de usuário +confirm_delete_account=Confirmar Exclusão +delete_account_title=Excluir Conta de Usuário delete_account_desc=Tem certeza que deseja apagar sua conta de usuário permanentemente? -email_notifications.enable=Habilitar notificações de e-mail -email_notifications.onmention=Somente e-mail com menção -email_notifications.disable=Desabilitar notificações de e-mail -email_notifications.submit=Atualizar preferências de e-mail +email_notifications.enable=Habilitar Notificações de E-mail +email_notifications.onmention=Somente E-mail com Menção +email_notifications.disable=Desabilitar Notificações de E-mail +email_notifications.submit=Definir Preferências de E-mail email_notifications.andyourown=E Suas Próprias Notificações visibility=Visibilidade do usuário @@ -883,7 +1028,10 @@ fork_to_different_account=Faça um fork para uma conta diferente fork_visibility_helper=A visibilidade do fork de um repositório não pode ser alterada. fork_branch=Branch a ser clonado para o fork all_branches=Todos os branches +view_all_branches=Ver todos branches +view_all_tags=Ver todas as tags use_template=Usar este modelo +open_with_editor=Abrir com %s download_zip=Baixar ZIP download_tar=Baixar TAR.GZ download_bundle=Baixar PACOTE @@ -891,6 +1039,8 @@ generate_repo=Gerar repositório generate_from=Gerar de repo_desc=Descrição repo_desc_helper=Digite uma breve descrição (opcional) +repo_no_desc=Descrição não fornecida +repo_lang=Linguagens repo_gitignore_helper=Selecione modelos do .gitignore. repo_gitignore_helper_desc=Escolha os arquivos que não serão rastreados da lista de modelos para linguagens comuns. Artefatos típicos gerados pelos compiladores de cada linguagem estão incluídos no .gitignore por padrão. issue_labels=Etiquetas de issue @@ -898,10 +1048,11 @@ issue_labels_helper=Selecione um conjunto de etiquetas de issue. license=Licença license_helper=Selecione um arquivo de licença. license_helper_desc=Uma licença define o que os outros podem e não podem fazer com o seu código. Não tem certeza qual é a mais adequada para o seu projeto? Veja Escolher uma licença. -readme=LEIA-ME -readme_helper=Selecione um modelo de arquivo LEIA-ME. +multiple_licenses=Múltiplas Licenças +readme=README +readme_helper=Selecione um modelo de arquivo README. readme_helper_desc=Aqui você pode escrever uma descrição completa para o seu projeto. -auto_init=Inicializar o repositório (adicionando .gitignore, licença e LEIA-ME) +auto_init=Inicializar o repositório (adicionando .gitignore, licença e README) trust_model_helper=Selecione o modelo de confiança para verificação de assinatura. As opções possíveis são: trust_model_helper_collaborator=Colaborador: Confiar em assinaturas de colaboradores trust_model_helper_committer=Committer: Confiar em assinaturas que correspondem aos committers @@ -919,10 +1070,12 @@ mirror_sync=sincronizado mirror_sync_on_commit=Sincronizar quando commits forem enviados mirror_address=Clonar de URL mirror_address_desc=Coloque todas as credenciais necessárias na seção de autorização. +mirror_address_url_invalid=O URL fornecido é inválido. Você deve escapar todos os componentes do URL corretamente. mirror_address_protocol_invalid=O URL fornecido é inválido. Somente locais http(s):// ou git:// podem ser usados para espelhamento. mirror_lfs=Armazenamento de Arquivo Grande (LFS) mirror_lfs_desc=Ativar espelhamento de dados LFS. mirror_lfs_endpoint=Destino LFS +mirror_lfs_endpoint_desc=A sincronização tentará usar o URL de clonagem para determinar o servidor LFS. Você também pode especificar um destino personalizado se os dados do repositório LFS forem armazenados em outro lugar. mirror_last_synced=Última sincronização mirror_password_placeholder=(inalterada) mirror_password_blank_placeholder=(não definida) @@ -931,10 +1084,11 @@ watchers=Observadores stargazers=Usuários que estrelaram stars_remove_warning=Isto irá remover todos os favoritos dados a este repositório. forks=Forks +stars=Favoritos reactions_more=e %d mais unit_disabled=O administrador do site desabilitou esta seção do repositório. language_other=Outra -adopt_preexisting_label=Adotar arquivos +adopt_preexisting_label=Adotar Arquivos adopt_preexisting=Adotar arquivos pré-existentes adopt_preexisting_content=Criar repositório a partir de %s adopt_preexisting_success=Arquivos adotados e repositório criado a partir de %s @@ -946,12 +1100,15 @@ blame_prior=Ver a responsabilização anterior a esta modificação transfer.accept=Aceitar transferência +transfer.accept_desc=`Transferir para "%s"` transfer.reject=Rejeitar transferência +transfer.reject_desc=`Cancelar a transferência para "%s"` transfer.no_permission_to_accept=Você não tem permissão para aceitar essa transferência. transfer.no_permission_to_reject=Você não tem permissão para rejeitar essa transferência. desc.private=Privado desc.public=Público +desc.public_access=Acesso Público desc.template=Template desc.internal=Interno desc.archived=Arquivado @@ -989,7 +1146,7 @@ migrate_items_wiki=Wiki migrate_items_milestones=Marcos migrate_items_labels=Etiquetas migrate_items_issues=Issues -migrate_items_pullrequests=Pull requests +migrate_items_pullrequests=Pull Requests migrate_items_merge_requests=Requisições de merge migrate_items_releases=Versões migrate_repo=Migrar repositório @@ -1024,6 +1181,7 @@ migrate.migrating_issues=Migrando Issues migrate.migrating_pulls=Migrando Pull Requests migrate.cancel_migrating_title=Cancelar migração migrate.cancel_migrating_confirm=Você quer cancelar essa migração? +migration_status=Status da migração mirror_from=espelhamento de forked_from=feito fork de @@ -1073,6 +1231,7 @@ releases=Versões tag=Tag released_this=lançou isto tagged_this=criou essa tag +file.title=%s em %s file_raw=Original file_history=Histórico file_view_source=Exibir código-fonte @@ -1080,6 +1239,7 @@ file_view_rendered=Ver Renderizado file_view_raw=Ver original file_permalink=Link permanente file_too_large=O arquivo é muito grande para ser mostrado. +file_is_empty=O arquivo está vazio. invisible_runes_header=`Este arquivo contém caracteres Unicode invisíveis` invisible_runes_description=`Este arquivo contém caracteres Unicode invisíveis que são indistinguíveis para humanos, mas que podem ser processados de forma diferente por um computador. Se você acha que isso é intencional, pode ignorar esse aviso com segurança. Use o botão Escapar para revelá-los` ambiguous_runes_header=`Este arquivo contém caracteres Unicode ambíguos` @@ -1106,7 +1266,7 @@ commit.contained_in_default_branch=Esse commit faz parte do branch padrão commit.load_referencing_branches_and_tags=Carregar branches e tags que fazem referência a este commit blame=Anotar download_file=Baixar arquivo -normal_view=Visão normal +normal_view=Visão Normal line=linha lines=linhas from_comment=(comentário) @@ -1117,7 +1277,9 @@ editor.upload_file=Enviar arquivo editor.edit_file=Editar arquivo editor.preview_changes=Visualizar alterações editor.cannot_edit_lfs_files=Arquivos LFS não podem ser editados na interface web. +editor.cannot_edit_too_large_file=O arquivo é muito grande para ser editado. editor.cannot_edit_non_text_files=Arquivos binários não podem ser editados na interface web. +editor.file_not_editable_hint=Mas você ainda pode renomear ou movê-lo. editor.edit_this_file=Editar arquivo editor.this_file_locked=Arquivo está bloqueado editor.must_be_on_a_branch=Você deve estar em um branch para propor alterações neste arquivo. @@ -1131,6 +1293,7 @@ editor.or=ou editor.cancel_lower=Cancelar editor.commit_signed_changes=Commit de alteradores assinadas editor.commit_changes=Aplicar commit das alterações +editor.add_tmpl=Adicionar '{filename}' editor.add=Adicionar %s editor.update=Atualizar %s editor.delete=Excluir %s @@ -1151,6 +1314,7 @@ editor.filename_is_invalid=O nome do arquivo é inválido: "%s". editor.branch_does_not_exist=Branch "%s" não existe neste repositório. editor.branch_already_exists=Branch "%s" já existe neste repositório. editor.directory_is_a_file=O nome do diretório "%s" já é usado como um nome de arquivo neste repositório. +editor.file_is_a_symlink=`"%s" é um link simbólico. Links simbólicos não podem ser editados no editor da web` editor.filename_is_a_directory=O nome do arquivo "%s" já é usado como um nome de diretório neste repositório. editor.file_changed_while_editing=O conteúdo do arquivo mudou desde que você começou a editar. Clique aqui para ver o que foi editado ou clique em Aplicar commit das alterações novamemente para sobreescrever estas alterações. editor.file_already_exists=Um arquivo com nome "%s" já existe neste repositório. @@ -1170,6 +1334,8 @@ editor.user_no_push_to_branch=O usuário não pode fazer push no branch editor.require_signed_commit=Branch requer um commit assinado editor.cherry_pick=Cherry-pick %s para: editor.revert=Reverter %s para: +editor.failed_to_commit=Falha ao criar commit das alterações. +editor.failed_to_commit_summary=Mensagem de Erro: commits.desc=Veja o histórico de alterações do código de fonte. @@ -1247,6 +1413,8 @@ issues.filter_milestones=Filtrar Marco issues.filter_projects=Filtrar Projeto issues.filter_labels=Filtrar Rótulo issues.filter_reviewers=Filtrar Revisor +issues.filter_no_results=Nenhum resultado +issues.filter_no_results_placeholder=Tente ajustar seus filtros de pesquisa. issues.new=Nova issue issues.new.title_empty=Título não pode ser em branco issues.new.labels=Etiquetas @@ -1273,7 +1441,7 @@ issues.choose.invalid_templates=%v modelo(s) inválido(s) encontrado(s) issues.choose.invalid_config=A configuração da issue contém erros: issues.no_ref=Nenhum branch/tag especificado issues.create=Criar issue -issues.new_label=Nova etiqueta +issues.new_label=Nova Etiqueta issues.new_label_placeholder=Nome da etiqueta issues.new_label_desc_placeholder=Descrição issues.create_label=Criar etiqueta @@ -1361,8 +1529,8 @@ issues.num_comments_1=%d comentário issues.num_comments=%d comentários issues.commented_at=`comentou %s` issues.delete_comment_confirm=Tem certeza que deseja excluir este comentário? -issues.context.copy_link=Copiar link -issues.context.quote_reply=Citar resposta +issues.context.copy_link=Copiar Link +issues.context.quote_reply=Citar Resposta issues.context.reference_issue=Referência em uma nova issue issues.context.edit=Editar issues.context.delete=Excluir @@ -1370,7 +1538,9 @@ issues.no_content=Nenhuma descrição fornecida. issues.close=Fechar issue issues.comment_pull_merged_at=aplicou o merge do commit %[1]s em %[2]s %[3]s issues.comment_manually_pull_merged_at=aplicou o merge manual do commit %[1]s em %[2]s %[3]s +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 %[2]s` issues.reopened_at=`reabriu esta issue %[2]s` @@ -1387,11 +1557,13 @@ issues.author_helper=Este usuário é o autor. issues.role.owner=Proprietário issues.role.owner_helper=Este usuário é o dono deste repositório. issues.role.member=Membro +issues.role.member_helper=Este usuário é um membro da organização proprietária deste repositório. issues.role.collaborator=Colaborador issues.role.collaborator_helper=Este usuário foi convidado para colaborar no repositório. issues.role.first_time_contributor=Primeira vez contribuindo issues.role.first_time_contributor_helper=Esta é a primeira contribuição deste usuário para o repositório. issues.role.contributor=Contribuidor +issues.role.contributor_helper=Este usuário já fez commit para o repositório. issues.re_request_review=Re-solicitar revisão issues.is_stale=Houve alterações nessa PR desde essa revisão issues.remove_request_review=Remover solicitação de revisão @@ -1405,6 +1577,7 @@ issues.save=Salvar issues.label_title=Nome da etiqueta issues.label_description=Descrição da etiqueta issues.label_color=Cor da etiqueta +issues.label_color_invalid=Cor inválida issues.label_exclusive=Exclusivo issues.label_archive=Arquivar etiqueta issues.label_archived_filter=Mostrar etiquetas arquivadas @@ -1453,10 +1626,17 @@ issues.delete=Apagar issues.delete.title=Apagar esta issue? issues.delete.text=Você realmente deseja excluir esta issue? (Isto irá remover permanentemente todo o conteúdo. Considere fechá-la em vez disso, se você pretende mantê-la arquivado) -issues.tracker=Contador de tempo +issues.tracker=Cronômetro +issues.timetracker_timer_start=Iniciar cronômetro +issues.timetracker_timer_stop=Parar cronômetro +issues.timetracker_timer_discard=Descartar cronômetro +issues.timetracker_timer_manually_add=Adicionar Tempo -issues.tracker_auto_close=Contador de tempo será parado automaticamente quando esta issue for fechada +issues.start_tracking_history=começou a trabalhar %s +issues.tracker_auto_close=Cronômetro será parado automaticamente quando esta issue for fechada issues.tracking_already_started=`Você já iniciou o cronômetro em outra issue!` +issues.stop_tracking=Parar Cronômetro +issues.stop_tracking_history=trabalhou por %[1]s %[2]s issues.cancel_tracking_history=`cronômetro cancelado %s` issues.del_time=Apagar este registro de tempo issues.del_time_history=`removeu tempo gasto %s` @@ -1466,7 +1646,7 @@ issues.add_time_sum_to_small=Nenhum tempo foi inserido. issues.time_spent_total=Tempo total gasto issues.time_spent_from_all_authors=`Tempo total gasto: %s` -issues.due_date=Data limite +issues.due_date=Data Limite issues.invalid_due_date_format=Formato da data limite inválido, deve ser 'dd/mm/aaaa'. issues.error_modifying_due_date=Falha ao modificar a data limite. issues.error_removing_due_date=Falha ao remover a data limite. @@ -1478,7 +1658,7 @@ issues.due_date_form=dd/mm/aaaa issues.due_date_form_add=Adicionar data limite issues.due_date_form_edit=Editar issues.due_date_form_remove=Remover -issues.due_date_not_set=Data limite não informada. +issues.due_date_not_set=Data limite não definida. issues.due_date_added=adicionou a data limite %s %s issues.due_date_modified=modificou a data limite de %[2]s para %[1]s %[3]s issues.due_date_remove=removeu a data limite %s %s @@ -1506,7 +1686,7 @@ issues.dependency.blocked_by_short=Depende de issues.dependency.remove_header=Remover dependência issues.dependency.issue_remove_text=Isto removerá a dependência desta issue. Continuar? issues.dependency.pr_remove_text=Isto removerá a dependência deste pull request. Continuar? -issues.dependency.setting=Habilitar dependências para issues e pull requests +issues.dependency.setting=Habilitar Dependências para Issues e Pull Requests issues.dependency.add_error_same_issue=Você não pode fazer uma issue depender de si mesma. issues.dependency.add_error_dep_issue_not_exist=Issue dependente não existe. issues.dependency.add_error_dep_not_exist=Dependência não existe. @@ -1515,6 +1695,7 @@ issues.dependency.add_error_dep_not_same_repo=Ambas as issues devem estar no mes issues.review.self.approval=Você não pode aprovar o seu próprio pull request. issues.review.self.rejection=Você não pode solicitar alterações em seu próprio pull request. issues.review.approve=aprovou estas alterações %s +issues.review.comment=revisou %s issues.review.dismissed_label=Rejeitada issues.review.left_comment=deixou um comentário issues.review.content.empty=Você precisa deixar um comentário indicando as alterações solicitadas. @@ -1522,6 +1703,7 @@ issues.review.reject=alterações solicitadas %s issues.review.wait=foi solicitada para revisão %s issues.review.add_review_request=solicitou revisão de %s %s issues.review.remove_review_request=removeu a solicitação de revisão para %s %s +issues.review.remove_review_request_self=recusou revisar %s issues.review.pending=Pendente issues.review.pending.tooltip=Este comentário não está atualmente visível para outros usuários. Para enviar seus comentários pendentes, selecione "%s" -> "%s/%s/%s" no topo da página. issues.review.review=Revisão @@ -1538,6 +1720,7 @@ issues.review.resolve_conversation=Resolver conversa issues.review.un_resolve_conversation=Conversa não resolvida issues.review.resolved_by=marcou esta conversa como resolvida issues.review.commented=Comentar +issues.assignee.error=Nem todos os responsáveis foram adicionados devido a um erro inesperado. issues.reference_issue.body=Conteúdo issues.content_history.deleted=excluído issues.content_history.edited=editado @@ -1577,7 +1760,7 @@ pulls.filter_changes_by_commit=Filtrar por commit pulls.nothing_to_compare=Estes branches são iguais. Não há nenhuma necessidade para criar um pull request. pulls.nothing_to_compare_and_allow_empty_pr=Estes branches são iguais. Este PR ficará vazio. pulls.has_pull_request=`Um pull request entre esses branches já existe: %[2]s#%[3]d` -pulls.create=Criar pull request +pulls.create=Criar Pull Request pulls.title_desc=quer aplicar o merge de %[1]d commits de %[2]s em %[3]s pulls.merged_title_desc=aplicou merge dos %[1]d commits de %[2]s em %[3]s %[4]s pulls.change_target_branch_at=`mudou o branch de destino de %s para %s %s` @@ -1675,8 +1858,10 @@ pulls.delete.title=Excluir este pull request? pulls.delete.text=Você realmente deseja excluir este pull request? (Isto irá remover permanentemente todo o conteúdo. Considere fechá-la em vez disso, se você pretende mantê-la arquivado) pulls.recently_pushed_new_branches=Você fez push no branch %[1]s %[2]s +pulls.upstream_diverging_merge=Sincronizar fork pull.deleted_branch=(excluído):%s +pull.agit_documentation=Veja a documentação sobre AGit milestones.new=Novo marco @@ -1696,7 +1881,7 @@ milestones.create_success=O marco "%s" foi criado. milestones.edit=Editar marco milestones.edit_subheader=Marcos organizam as issues e acompanham o progresso. milestones.cancel=Cancelar -milestones.modify=Atualizar marco +milestones.modify=Atualizar Marco milestones.edit_success=O marco "%s" foi atualizado. milestones.deletion=Excluir marco milestones.deletion_desc=A exclusão deste marco irá removê-lo de todas as issues. Tem certeza que deseja continuar? @@ -1762,12 +1947,12 @@ activity.period.quarterly=3 meses activity.period.semiyearly=6 meses activity.period.yearly=1 ano activity.overview=Visão geral -activity.active_prs_count_1=%d Pull request ativo -activity.active_prs_count_n=%d Pull requests ativos -activity.merged_prs_count_1=Pull request com merge aplicado -activity.merged_prs_count_n=Pull requests com merge aplicado -activity.opened_prs_count_1=Pull request proposto -activity.opened_prs_count_n=Pull requests propostos +activity.active_prs_count_1=%d Pull Request Ativo +activity.active_prs_count_n=%d Pull Requests Ativos +activity.merged_prs_count_1=Pull Request com Merge Aplicado +activity.merged_prs_count_n=Pull Requests com Merge Aplicado +activity.opened_prs_count_1=Pull Request Proposto +activity.opened_prs_count_n=Pull Requests Propostos activity.title.user_1=%d usuário activity.title.user_n=%d usuários activity.title.prs_1=%d Pull request @@ -1776,20 +1961,20 @@ activity.title.prs_merged_by=%s com merge aplicado por %s activity.title.prs_opened_by=%s proposto(s) por %s activity.merged_prs_label=Merge aplicado activity.opened_prs_label=Proposto -activity.active_issues_count_1=%d Issue ativa -activity.active_issues_count_n=%d Issues ativas -activity.closed_issues_count_1=Issue fechada -activity.closed_issues_count_n=Issues fechadas +activity.active_issues_count_1=%d Issue Ativa +activity.active_issues_count_n=%d Issues Ativas +activity.closed_issues_count_1=Issue Fechada +activity.closed_issues_count_n=Issues Fechadas activity.title.issues_1=+%d Issue activity.title.issues_n=+%d Issues activity.title.issues_closed_from=%s fechada por %s activity.title.issues_created_by=%s criada por %s activity.closed_issue_label=Fechado -activity.new_issues_count_1=Nova issue -activity.new_issues_count_n=Novas issues +activity.new_issues_count_1=Nova Issue +activity.new_issues_count_n=Novas Issues activity.new_issue_label=Aberta -activity.title.unresolved_conv_1=%d conversa não resolvida -activity.title.unresolved_conv_n=%d conversas não resolvidas +activity.title.unresolved_conv_1=%d Conversa Não Resolvida +activity.title.unresolved_conv_n=%d Conversas Não Resolvidas activity.unresolved_conv_desc=Estas issues foram recentemente alteradas e pull requests ainda não foram resolvidos. activity.unresolved_conv_label=Aberta activity.title.releases_1=%d Versão @@ -1824,6 +2009,7 @@ contributors.contribution_type.deletions=Exclusões settings=Configurações settings.options=Repositório +settings.public_access=Acesso Público settings.collaboration=Colaboradores settings.collaboration.admin=Administrador settings.collaboration.write=Escrita @@ -1832,7 +2018,7 @@ settings.collaboration.owner=Proprietário settings.collaboration.undefined=Indefinido settings.hooks=Webhooks settings.githooks=Hooks do Git -settings.basic_settings=Configurações básicas +settings.basic_settings=Configurações Básicas settings.mirror_settings=Opções de espelhamento settings.mirror_settings.docs=Configure o seu repositório para sincronizar automaticamente commits, tags e branches de outro repositório. settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=No momento, isso só pode ser feito no menu "Nova migração". Para obter mais informações, consulte: @@ -1862,7 +2048,7 @@ settings.use_external_wiki=Usar wiki externa settings.external_wiki_url=URL externa da wiki settings.external_wiki_url_error=A URL da wiki externa não é válida. settings.external_wiki_url_desc=Visitantes são redirecionados para a URL da wiki externa ao clicar na aba da wiki. -settings.issues_desc=Habilitar issue tracker para o repositório +settings.issues_desc=Habilitar Issue Tracker para o Repositório settings.use_internal_issue_tracker=Usar o issue tracker nativo settings.use_external_issue_tracker=Usar issue tracker externo settings.external_tracker_url=URL do issue tracker externo @@ -1896,7 +2082,7 @@ settings.admin_stats_indexer=Indexador de Estatísticas do Código settings.admin_indexer_commit_sha=Último SHA indexado settings.admin_indexer_unindexed=Não indexado settings.reindex_button=Adicionar à fila de reindexação -settings.reindex_requested=Reindexação requisitada +settings.reindex_requested=Reindexação Requisitada settings.danger_zone=Zona de perigo settings.new_owner_has_same_repo=O novo proprietário já tem um repositório com o mesmo nome. Por favor, escolha outro nome. settings.convert=Converter para repositório tradicional @@ -1935,9 +2121,9 @@ settings.trust_model.collaboratorcommitter.long=Colaborador+Committer: Confiar n settings.wiki_delete=Excluir dados da wiki settings.wiki_delete_desc=A exclusão de dados da wiki é permanente e não pode ser desfeita. settings.wiki_delete_notices_1=- Isso excluirá e desabilitará permanentemente a wiki do repositório %s. -settings.confirm_wiki_delete=Excluir dados da wiki +settings.confirm_wiki_delete=Excluir Dados da Wiki settings.wiki_deletion_success=Os dados da wiki do repositório foi excluídos. -settings.delete=Excluir este repositório +settings.delete=Excluir Este Repositório settings.delete_desc=A exclusão de um repositório é permanente e não pode ser desfeita. settings.delete_notices_1=- Esta operação NÃO PODERÁ ser desfeita. settings.delete_notices_fork_1=- Forks deste repositório se tornarão independentes após a exclusão. @@ -1967,6 +2153,7 @@ settings.hooks_desc=Webhooks automaticamente fazem requisições de HTTP POST pa settings.webhook_deletion=Remover webhook settings.webhook_deletion_desc=A exclusão de um webhook exclui suas configurações e o histórico de entrega. Continuar? settings.webhook_deletion_success=O webhook foi removido. +settings.webhook.test_delivery=Testar Evento de Push settings.webhook.request=Solicitação settings.webhook.response=Resposta settings.webhook.headers=Cabeçalhos @@ -2005,11 +2192,13 @@ settings.event_wiki_desc=Página da wiki criada, renomeada, editada ou excluída settings.event_release=Versão settings.event_release_desc=Versão publicada, atualizada ou excluída em um repositório. settings.event_push=Push +settings.event_force_push=Forçar Push settings.event_push_desc=Git push para o repositório. settings.event_repository=Repositório settings.event_repository_desc=Repositório criado ou excluído. settings.event_header_issue=Eventos da Issue settings.event_issues=Issues +settings.event_issues_desc=Issue aberta, fechada, reaberta, editada ou excluída. settings.event_issue_assign=Issue Atribuída settings.event_issue_assign_desc=Issue atribuída ou não atribuída. settings.event_issue_label=Issue Rotulada @@ -2020,6 +2209,7 @@ settings.event_issue_comment=Comentário da issue settings.event_issue_comment_desc=Comentário da issue criado, editado ou excluído. settings.event_header_pull_request=Eventos de Pull Request settings.event_pull_request=Pull request +settings.event_pull_request_desc=Pull request aberto, fechado, reaberto, editado ou excluído. settings.event_pull_request_assign=Pull Request Atribuído settings.event_pull_request_assign_desc=Pull request atribuído ou desatribuído. settings.event_pull_request_label=Pull Request Rotulado @@ -2066,7 +2256,7 @@ settings.packagist_username=Nome de usuário no Packagist settings.packagist_api_token=Token de API settings.packagist_package_url=URL do pacote do Packagist settings.deploy_keys=Chaves de Deploy -settings.add_deploy_key=Nova chave +settings.add_deploy_key=Nova Chave de Deploy settings.deploy_key_desc=As chaves de deploy possuem somente acesso de leitura (pull) ao repositório. settings.is_writable=Habilitar acesso de escrita settings.is_writable_info=Permitir que esta chave de deploy faça push para o repositório. @@ -2078,14 +2268,22 @@ settings.key_name_used=Uma chave de deploy já existe com esse mesmo nome. settings.deploy_key_deletion=Remover chave de deploy settings.deploy_key_deletion_desc=A exclusão de uma chave de deploy irá revogar o seu acesso a este repositório. Continuar? settings.deploy_key_deletion_success=A chave de deploy foi removida. +settings.branches=Branches +settings.protected_branch=Proteção de Branch settings.protected_branch.save_rule=Salvar Regra settings.protected_branch.delete_rule=Excluir Regra +settings.protected_branch_can_push=Permitir push? +settings.protected_branch_can_push_yes=Você pode fazer push +settings.protected_branch_can_push_no=Você não pode fazer push settings.protect_this_branch=Habilitar Proteção de Branch settings.protect_this_branch_desc=Previne a exclusão e restringe o merge e push para o branch. settings.protect_disable_push=Desabilitar push settings.protect_disable_push_desc=Nenhum push será permitido neste branch. -settings.protect_enable_push=Habilitar push +settings.protect_disable_force_push=Desativar Push Forçado +settings.protect_disable_force_push_desc=Nenhum push forçado será permitido para este branch. +settings.protect_enable_push=Habilitar Push settings.protect_enable_push_desc=Qualquer pessoa com acesso de escrita terá permissão para realizar push neste branch (mas não forçar o push). +settings.protect_enable_force_push_all=Ativar Push Forçado settings.protect_enable_merge=Permitir merge settings.protect_check_status_contexts=Habilitar verificação de status settings.protect_check_status_contexts_list=Verificações de status encontradas na última semana para este repositório @@ -2098,6 +2296,8 @@ settings.protect_branch_name_pattern=Padrão de Nome de Branch Protegida settings.protect_patterns=Padrões settings.protect_protected_file_patterns=Padrões de arquivos protegidos (separados usando ponto e vírgula ';'): settings.protect_unprotected_file_patterns=Padrões de arquivos desprotegidos (separados usando ponto e vírgula ';'): +settings.add_protected_branch=Habilitar proteção +settings.delete_protected_branch=Desabilitar proteção settings.update_protect_branch_success=Proteção do branch "%s" foi atualizada. settings.remove_protected_branch_success=Proteção do branch "%s" foi desabilitada. settings.remove_protected_branch_failed=Removendo regra de proteção de branch "%s" falhou. @@ -2130,8 +2330,10 @@ settings.chat_id=ID do Chat settings.matrix.homeserver_url=URL do Homeserver settings.matrix.room_id=ID da Sala settings.matrix.message_type=Tipo de Mensagem +settings.visibility.private.button=Tornar Privado +settings.visibility.public.button=Tornar Público settings.archive.button=Arquivar repositório -settings.archive.header=Arquivar este repositório +settings.archive.header=Arquivar Este Repositório settings.archive.success=O repositório foi arquivado com sucesso. settings.archive.error=Um erro ocorreu enquanto estava sendo arquivado o repositório. Veja o log para mais detalhes. settings.archive.error_ismirror=Você não pode arquivar um repositório espelhado. @@ -2203,6 +2405,7 @@ diff.show_more=Mostrar mais diff.load=Carregar Diff diff.generated=gerado diff.vendored=externo +diff.comment.add_line_comment=Adicionar comentário na linha diff.comment.placeholder=Deixe um comentário diff.comment.add_single_comment=Adicionar um único comentário diff.comment.add_review_comment=Adicionar comentário @@ -2238,7 +2441,7 @@ release.edit=editar release.ahead.commits=%d commits release.ahead.target=para %s desde esta versão tag.ahead.target=para %s desde esta tag -release.source_code=Código fonte +release.source_code=Código Fonte release.new_subheader=Lançamentos organizam versões do projeto. release.edit_subheader=Lançamentos organizam versões do projeto. release.tag_name=Nome da tag @@ -2255,7 +2458,7 @@ release.cancel=Cancelar release.publish=Publicar versão release.save_draft=Salvar rascunho release.edit_release=Atualizar versão -release.delete_release=Excluir versão +release.delete_release=Excluir Versão release.delete_tag=Apagar Tag release.deletion=Excluir versão release.deletion_desc=A exclusão de uma versão apenas a remove do Gitea. Isso não afetará a tag do Git, o conteúdo do seu repositório ou seu histórico. Continuar? @@ -2269,14 +2472,14 @@ release.tag_already_exist=Este nome de tag já existe. release.downloads=Downloads release.download_count=Downloads: %s release.add_tag_msg=Use o título e o conteúdo do lançamento como mensagem da tag. -release.add_tag=Criar apenas a tag +release.add_tag=Criar Apenas a Tag release.releases_for=Versões para %s release.tags_for=Tags para %s branch.name=Nome do Branch branch.already_exists=Um branch com o nome "%s" já existe. branch.delete_head=Excluir -branch.delete=`Excluir branch "%s"` +branch.delete=`Excluir Branch "%s"` branch.delete_html=Excluir Branch branch.deletion_success=Branch "%s" excluído. branch.deletion_failed=Falha ao excluir o branch "%s". @@ -2290,9 +2493,10 @@ branch.restore_success=Branch "%s" restaurado. branch.restore_failed=Ocorreu um erro ao restaurar o branch "%s". branch.protected_deletion_failed=Branch "%s" é protegido. Ele não pode ser excluído. branch.default_deletion_failed=Branch "%s" é o branch padrão. Ele não pode ser excluído. -branch.restore=`Restaurar branch "%s"` -branch.download=`Baixar branch "%s"` -branch.rename=`Renomear branch "%s"` +branch.default_branch_not_exist=Branch padrão "%s" não existe. +branch.restore=`Restaurar Branch "%s"` +branch.download=`Baixar Branch "%s"` +branch.rename=`Renomear Branch "%s"` branch.included_desc=Este branch faz parte do branch padrão branch.included=Incluído branch.create_new_branch=Criar branch a partir do branch: @@ -2304,6 +2508,7 @@ branch.create_branch_operation=Criar branch branch.new_branch=Criar novo branch branch.new_branch_from=`Criar novo branch a partir de "%s"` branch.renamed=Branch %s foi renomeado para %s. +branch.commits_no_divergence=O mesmo que branch %[1]s tag.create_tag=Criar tag %s tag.create_tag_operation=Criar tag @@ -2323,43 +2528,50 @@ error.csv.unexpected=Não é possível renderizar este arquivo porque ele conté error.csv.invalid_field_count=Não é possível renderizar este arquivo porque ele tem um número errado de campos na linha %d. [graphs] +component_loading=Carregando %s… component_loading_failed=Não foi possível carregar %s component_loading_info=Isto pode demorar um pouco… +component_failed_to_load=Ocorreu um erro inesperado. +contributors.what=contribuições +recent_commits.what=commits recentes [org] -org_name_holder=Nome da organização -org_full_name_holder=Nome completo da organização +org_name_holder=Nome da Organização +org_full_name_holder=Nome Completo da Organização org_name_helper=Nomes de organização devem ser curtos e memoráveis. -create_org=Criar organização +create_org=Criar Organização repo_updated=Atualizado members=Membros teams=Equipes code=Código lower_members=membros lower_repositories=repositórios -create_new_team=Nova equipe -create_team=Criar equipe +create_new_team=Nova Equipe +create_team=Criar Equipe org_desc=Descrição -team_name=Nome da equipe +team_name=Nome da Equipe team_desc=Descrição team_name_helper=Nomes de equipe devem ser curtos e memoráveis. team_desc_helper=Descreva a finalidade ou o papel da equipe. team_access_desc=Acesso ao repositório team_permission_desc=Permissão -team_unit_desc=Permitir o acesso a seções de repositório +team_unit_desc=Permitir o Acesso a Seções de Repositório team_unit_disabled=(Desabilitado) form.name_reserved=O nome de organização "%s" está reservado. +form.name_pattern_not_allowed=O padrão "%s" não é permitido em um nome de organização. form.create_org_not_allowed=Você não tem permissão para criar uma organização. settings=Configurações settings.options=Organização -settings.full_name=Nome completo +settings.full_name=Nome Completo +settings.email=E-mail de contato settings.website=Site settings.location=Localização settings.permission=Permissões settings.repoadminchangeteam=O administrador do repositório pode adicionar e remover o acesso para equipes settings.visibility=Visibilidade +settings.change_visibility=Alterar Visibilidade settings.visibility.public=Pública settings.visibility.limited=Limitado (Visível apenas para usuários autenticados) settings.visibility.limited_shortname=Limitado @@ -2369,22 +2581,24 @@ settings.visibility.private_shortname=Privado settings.update_settings=Atualizar Configurações settings.update_setting_success=Configurações da organização foram atualizadas. +settings.rename=Renomear Organização +settings.rename_new_org_name=Novo Nome da Organização settings.update_avatar_success=O avatar da organização foi atualizado. -settings.delete=Excluir organização -settings.delete_account=Excluir esta organização +settings.delete=Excluir Organização +settings.delete_account=Excluir Esta Organização settings.delete_prompt=A organização será excluída permanentemente. Isto NÃO PODERÁ ser desfeito! -settings.confirm_delete_account=Confirmar exclusão +settings.confirm_delete_account=Confirmar Exclusão settings.hooks_desc=Adicionar Webhooks que serão acionados para todos os repositórios desta organização. settings.labels_desc=Adicionar rótulos que possam ser usadas em issues para todos os repositórios desta organização. -members.membership_visibility=Visibilidade da associação: +members.membership_visibility=Visibilidade da Associação: members.public=Público members.public_helper=tornar privado members.private=Privado members.private_helper=tornar público -members.member_role=Categoria de membro: +members.member_role=Categoria de Membro: members.owner=Proprietário members.member=Membro members.remove=Remover @@ -2392,7 +2606,7 @@ members.remove.detail=Remover %[1]s de %[2]s? members.leave=Sair members.leave.detail=Sair de %s? members.invite_desc=Adicionar novo membro em %s: -members.invite_now=Convidar agora +members.invite_now=Convidar Agora teams.join=Juntar-se teams.leave=Deixar @@ -2406,25 +2620,25 @@ teams.read_access=Leitura teams.read_access_helper=Os membros podem ver e clonar os repositórios da equipe. teams.write_access=Escrita teams.write_access_helper=Os membros podem ler e realizar push para os repositórios da equipe. -teams.admin_access=Acesso de administrador +teams.admin_access=Acesso de Administrador teams.admin_access_helper=Os membros podem realizar pull e push em repositórios da equipe e adicionar colaboradores a eles. teams.no_desc=Esta equipe não tem descrição teams.settings=Configurações teams.owners_permission_desc=Proprietários tem acesso total a todos repositórios e também direitos de administrador na organização. -teams.members=Membros da equipe -teams.update_settings=Atualizar configurações -teams.delete_team=Excluir equipe -teams.add_team_member=Adicionar membro na equipe +teams.members=Membros da Equipe +teams.update_settings=Atualizar Configurações +teams.delete_team=Excluir Equipe +teams.add_team_member=Adicionar Membro na Equipe teams.invite_team_member=Convidar para %s -teams.invite_team_member.list=Convites pendentes -teams.delete_team_title=Excluir equipe +teams.invite_team_member.list=Convites Pendentes +teams.delete_team_title=Excluir Equipe teams.delete_team_desc=A exclusão de uma equipe revoga o acesso ao repositório de seus membros. Continuar? teams.delete_team_success=A equipe foi excluída. teams.read_permission_desc=Essa equipe concede acesso para Leitura: membros podem ver e clonar os repositórios da equipe. teams.write_permission_desc=Esta equipe concede acesso para escrita: Membros podem ler e fazer push para os repositórios da equipe. teams.admin_permission_desc=Esta equipe concede acesso de Administrador: Membros podem ler, fazer push e adicionar outros colaboradores para os repositórios da equipe. teams.create_repo_permission_desc=Além disso, esta equipe concede permissão de Criar repositório: membros podem criar novos repositórios na organização. -teams.repositories=Repositórios da equipe +teams.repositories=Repositórios da Equipe teams.remove_all_repos_title=Remover todos os repositórios da equipe teams.remove_all_repos_desc=Isto irá remover todos os repositórios da equipe. teams.add_all_repos_title=Adicionar todos os repositórios @@ -2432,6 +2646,7 @@ teams.add_all_repos_desc=Isto irá adicionar todos os repositórios da organiza teams.add_duplicate_users=Usuário já é um membro da equipe. teams.repos.none=Nenhum repositório pode ser acessado por essa equipe. teams.members.none=Nenhum membro nesta equipe. +teams.members.blocked_user=Não é possível adicionar o usuário porque ele está bloqueado pela organização. teams.specific_repositories=Repositórios específicos teams.specific_repositories_helper=Os membros terão acesso apenas aos repositórios explicitamente adicionados à equipe. Selecionar este não removerá automaticamente os repositórios já adicionados com Todos os repositórios. teams.all_repositories=Todos os repositórios @@ -2443,21 +2658,27 @@ teams.invite.title=Você foi convidado para fazer parte da equipe %s%s @@ -2956,6 +3202,7 @@ raw_minutes=minutos [dropzone] default_message=Arraste e solte arquivos aqui, ou clique para selecioná-los. +invalid_input_type=Você não pode enviar arquivos deste tipo. file_too_big=Tamanho de arquivo ({{filesize}} MB) excede o máximo de ({{maxFilesize}} MB). remove_file=Remover arquivo @@ -2981,6 +3228,8 @@ error.no_committer_account=Nenhuma conta vinculada ao e-mail do autor do commit error.no_gpg_keys_found=Nenhuma chave conhecida encontrada para esta assinatura no banco de dados error.not_signed_commit=Não é um commit assinado error.failed_retrieval_gpg_keys=Falha em obter qualquer chave anexada à conta do autor do commit +error.probable_bad_signature=AVISO! Embora exista uma chave com este ID no banco de dados, ela não verifica este commit! Este commit é SUSPEITO. +error.probable_bad_default_signature=AVISO! Embora a chave padrão tenha este ID, ela não verifica este commit! Este commit é SUSPEITO. [units] unit=Unidade @@ -2993,6 +3242,7 @@ desc=Gerenciar pacotes do repositório. empty=Não há pacotes ainda. empty.documentation=Para obter mais informações sobre o registro de pacotes, consulte a documentação. empty.repo=Você enviou um pacote, mas ele não está aqui? Vá para configurações do pacote e vincule-o a este repositório. +registry.documentation=Para obter mais informações sobre o registro %s, consulte a documentação. filter.type=Tipo filter.type.all=Todos filter.no_result=Seu filtro não produziu resultados. @@ -3016,45 +3266,60 @@ versions=Versões versions.view_all=Ver todas dependency.id=ID dependency.version=Versão +alpine.registry=Configure este registro adicionando o URL no arquivo /etc/apk/repositories: alpine.registry.key=Baixe a chave RSA pública do registro para a pasta /etc/apk/keys/ para verificar a assinatura do índice: alpine.registry.info=Escolha o $branch e $repository da lista abaixo. alpine.install=Para instalar o pacote, execute o seguinte comando: -alpine.repository=Informações do repositório +alpine.repository=Informações do Repositório +alpine.repository.branches=Branches alpine.repository.repositories=Repositórios alpine.repository.architectures=Arquiteturas -arch.repository=Informações do repositório +arch.repository=Informações do Repositório arch.repository.repositories=Repositórios arch.repository.architectures=Arquiteturas +cargo.registry=Configure este registro no arquivo de configuração do Cargo (por exemplo ~/.cargo/config.toml): cargo.install=Para instalar o pacote usando Cargo, execute o seguinte comando: +chef.registry=Configure este registro em seu arquivo ~/.chef/config.rb: chef.install=Para instalar o pacote, execute o seguinte comando: +composer.registry=Configure este registro em seu arquivo ~/.composer/config.json: composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando: composer.dependencies=Dependências composer.dependencies.development=Dependências de Desenvolvimento conan.details.repository=Repositório +conan.registry=Configure este registro pela linha de comando: conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando: +conda.registry=Configure este registro como um repositório Conda no arquivo .condarc: conda.install=Para instalar o pacote usando o Conda, execute o seguinte comando: container.details.type=Tipo de Imagem container.details.platform=Plataforma container.pull=Puxe a imagem pela linha de comando: +container.digest=Digest container.multi_arch=S.O. / Arquitetura container.layers=Camadas da Imagem container.labels=Rótulos container.labels.key=Chave container.labels.value=Valor +cran.registry=Configure este registro no arquivo Rprofile.site: cran.install=Para instalar o pacote, execute o seguinte comando: +debian.registry=Configure este registro pela linha de comando: debian.registry.info=Escolha uma $distribution e um $component da lista abaixo: debian.install=Para instalar o pacote, execute o seguinte comando: -debian.repository=Informações do repositório +debian.repository=Informações do Repositório debian.repository.distributions=Distribuições debian.repository.components=Componentes debian.repository.architectures=Arquiteturas generic.download=Baixar pacote pela linha de comando: go.install=Instale o pacote usando o comando: +helm.registry=Configure este registro pela linha de comando: helm.install=Para instalar o pacote, execute o seguinte comando: +maven.registry=Configure este registro no arquivo pom.xml do seu projeto: +maven.install=Para usar o pacote inclua o seguinte no bloco de dependencies no arquivo pom.xml: maven.install2=Executar via linha de comando: maven.download=Para baixar a dependência, execute via linha de comando: +nuget.registry=Configurar este registro pela linha de comando: nuget.install=Para instalar o pacote usando NuGet, execute o seguinte comando: nuget.dependency.framework=Estrutura Alvo +npm.registry=Configure este registro no arquivo .npmrc do seu projeto: npm.install=Para instalar o pacote usando o npm, execute o seguinte comando: npm.install2=ou adicione-o ao arquivo package.json: npm.dependencies=Dependências @@ -3065,17 +3330,20 @@ npm.details.tag=Tag pub.install=Para instalar o pacote usando Dart, execute o seguinte comando: pypi.requires=Requer Python pypi.install=Para instalar o pacote usando pip, execute o seguinte comando: +rpm.registry=Configure este registro pela linha de comando: rpm.distros.redhat=em distribuições baseadas no RedHat rpm.distros.suse=em distribuições baseadas no SUSE rpm.install=Para instalar o pacote, execute o seguinte comando: -rpm.repository=Informações do repositório +rpm.repository=Informações do Repositório rpm.repository.architectures=Arquiteturas +rpm.repository.multiple_groups=Esse pacote está disponível em vários grupos. rubygems.install=Para instalar o pacote usando gem, execute o seguinte comando: rubygems.install2=ou adicione-o ao Gemfile: rubygems.dependencies.runtime=Dependências de Execução rubygems.dependencies.development=Dependências de Desenvolvimento rubygems.required.ruby=Requer o Ruby versão rubygems.required.rubygems=Requer o RubyGem versão +swift.registry=Configure este registro pela linha de comando: swift.install=Adicione o pacote em seu arquivo Package.swift: swift.install2=e execute o seguinte comando: vagrant.install=Para adicionar uma Vagrant box, execute o seguinte comando: @@ -3083,6 +3351,7 @@ settings.link=Vincular este pacote a um repositório settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório. settings.link.select=Selecionar Repositório settings.link.button=Atualizar Link do Repositório +settings.link.success=Link do repositório foi atualizado com sucesso. settings.link.error=Falha ao atualizar o link do repositório. settings.delete=Excluir o pacote settings.delete.description=A exclusão de um pacote é permanente e não pode ser desfeita. @@ -3091,13 +3360,17 @@ settings.delete.success=O pacote foi excluído. settings.delete.error=Falha ao excluir o pacote. owner.settings.cargo.title=Índice do Registro Cargo owner.settings.cargo.initialize=Iniciar Índice +owner.settings.cargo.initialize.description=É necessário um repositório Git de índice especial para usar o registro do Cargo. O uso dessa opção (re)criará o repositório e o configurará automaticamente. owner.settings.cargo.initialize.error=Falha ao inicializar índice Cargo: %v owner.settings.cargo.initialize.success=O índice Cargo foi criado com sucesso. owner.settings.cargo.rebuild=Reconstruir Índice +owner.settings.cargo.rebuild.description=A recompilação pode ser útil se o índice não estiver sincronizado com os pacotes Cargo armazenados. owner.settings.cargo.rebuild.error=Falha ao reconstruir índice Cargo: %v +owner.settings.cargo.rebuild.success=O índice Cargo foi reconstruído com sucesso. owner.settings.cleanuprules.title=Gerenciar Regras de Limpeza owner.settings.cleanuprules.add=Adicionar Regra de Limpeza owner.settings.cleanuprules.edit=Editar Regra de Limpeza +owner.settings.cleanuprules.none=Não há regras de limpeza disponíveis. Consulte a documentação. owner.settings.cleanuprules.preview=Pré-visualizar Regra de Limpeza owner.settings.cleanuprules.preview.overview=%d pacotes agendados para serem removidos. owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote. @@ -3116,6 +3389,7 @@ owner.settings.cleanuprules.success.update=Regra de limpeza foi atualizada. owner.settings.cleanuprules.success.delete=Regra de limpeza foi excluída. owner.settings.chef.title=Registro Chef owner.settings.chef.keypair=Gerar par de chaves +owner.settings.chef.keypair.description=Um par de chaves é necessário para autenticar o registro do Chef. Se você já tiver gerado um par de chaves antes, a geração de um novo par de chaves descartará o par de chaves antigo. [secrets] secrets=Segredos @@ -3175,6 +3449,7 @@ runners.delete_runner=Deletar esse runner runners.delete_runner_success=Runner excluído com sucesso runners.delete_runner_failed=Falha ao excluir runner runners.delete_runner_header=Confirme para excluir este runner +runners.delete_runner_notice=Se uma tarefa estiver sendo executada neste runner, ela será encerrada e marcada como falha. Pode quebrar o workflow de construção. runners.none=Nenhum runner disponível runners.status.unspecified=Desconhecido runners.status.idle=Inativo @@ -3189,24 +3464,49 @@ runs.commit=Commit runs.scheduled=Agendado runs.pushed_by=push feito por runs.invalid_workflow_helper=O arquivo de configuração do workflow é inválido. Por favor, verifique seu arquivo de configuração: %s +runs.no_matching_online_runner_helper=Nenhum runner online com a etiqueta: %s runs.actor=Ator runs.status=Status runs.actors_no_select=Todos os atores runs.status_no_select=Todos os Status runs.no_results=Não houve correspondência de resultados. +runs.no_workflows=Ainda não existem workflows. +runs.no_workflows.quick_start=Não sabe como começar com as Ações do Gitea? Veja o guia de início rápido. +runs.no_workflows.documentation=Para obter mais informações sobre as Ações do Gitea, consulte a documentação. +runs.no_runs=O workflow ainda não foi executado. runs.empty_commit_message=(mensagem de commit vazia) +workflow.disable=Desabilitar Workflow +workflow.disable_success=Workflow '%s' desativado com sucesso. +workflow.enable=Habilitar Workflow +workflow.enable_success=Workflow '%s' habilitado com sucesso. +workflow.disabled=Workflow está desativado. need_approval_desc=Precisa de aprovação para executar workflows para pull request do fork. +variables=Variáveis +variables.management=Gerenciamento de Variáveis +variables.creation=Adicionar Variável +variables.none=Ainda não há variáveis. +variables.deletion=Remover variável +variables.deletion.description=A remoção de uma variável é permanente e não pode ser desfeita. Continuar? +variables.id_not_exist=A variável com o ID %d não existe. +variables.edit=Editar Variável +variables.deletion.failed=Falha ao remover a variável. +variables.deletion.success=A variável foi removida. +variables.creation.failed=Falha ao adicionar a variável. +variables.creation.success=A variável "%s" foi adicionada. +variables.update.failed=Falha ao editar a variável. +variables.update.success=A variável foi editada. [projects] -type-1.display_name=Projeto individual -type-2.display_name=Projeto do repositório -type-3.display_name=Projeto da organização +type-1.display_name=Projeto Individual +type-2.display_name=Projeto do Repositório +type-3.display_name=Projeto da Organização [git.filemode] +changed_filemode=%[1]s → %[2]s ; Ordered by git filemode value, ascending. E.g. directory has "040000", normal file has "100644", … directory=Diretório normal_file=Arquivo normal diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 2b96ed51027..ed611d25993 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -44,6 +44,7 @@ webauthn_use_twofa=Usar um código de dois passos do seu telefone webauthn_error=Não foi possível ler a sua chave de segurança. webauthn_unsupported_browser=O seu navegador não oferece suporte ao WebAuthn. webauthn_error_unknown=Ocorreu um erro desconhecido. Tente novamente, por favor. +webauthn_error_insecure=WebAuthn apenas suporta conexões seguras. Para testar sobre HTTP, pode usar a origem "localhost" ou "127.0.0.1". webauthn_error_unable_to_process=O servidor não conseguiu processar o seu pedido. webauthn_error_duplicated=A chave de segurança não é permitida neste pedido. Certifique-se de que a chave não está já registada. webauthn_error_empty=Tem de definir um nome para esta chave. @@ -119,6 +120,7 @@ error404=A página que pretende aceder não existe ou n error503=O servidor não conseguiu concluir o seu pedido. Tente novamente mais tarde. go_back=Voltar invalid_data=Dados inválidos: %v +nothing_has_been_changed=Nada foi alterado. never=Nunca unknown=Desconhecido @@ -167,6 +169,7 @@ no_results_found=Não foram encontrados quaisquer resultados. internal_error_skipped=Ocorreu um erro interno mas foi ignorado: %s [search] +search=Pesquisar… type_tooltip=Tipo de pesquisa fuzzy=Aproximada fuzzy_tooltip=Incluir também os resultados que estejam próximos do termo de pesquisa @@ -176,10 +179,23 @@ regexp=Regexp regexp_tooltip=Incluir apenas os resultados que correspondam ao termo de pesquisa com expressões regulares exact=Fiel exact_tooltip=Incluir somente os resultados que correspondam rigorosamente ao termo de pesquisa +repo_kind=Pesquisar repositórios… +user_kind=Pesquisar utilizadores… +org_kind=Pesquisar organizações… +team_kind=Pesquisar equipas… +code_kind=Pesquisar código-fonte… code_search_unavailable=A pesquisa de código não está disponível, neste momento. Entre em contacto com o administrador. code_search_by_git_grep=Os resultados da pesquisa no código-fonte neste momento são fornecidos pelo "git grep". Esses resultados podem ser melhores se o administrador habilitar o indexador do repositório. +package_kind=Pesquisar pacotes… +project_kind=Pesquisar planeamentos… +branch_kind=Pesquisar ramos… +tag_kind=Pesquisar etiquetas… tag_tooltip=Pesquisar etiquetas correspondentes. Use '%' para corresponder a qualquer sequência de números. +commit_kind=Pesquisar cometimentos… +runner_kind=Pesquisar executores… no_results=Não foram encontrados resultados correspondentes. +issue_kind=Pesquisar questões… +pull_kind=Pesquisar puxadas… keyword_search_unavailable=Pesquisar por palavra-chave não está disponível, neste momento. Entre em contacto com o administrador. [aria] @@ -215,6 +231,8 @@ buttons.enable_monospace_font=Habilitar tipo de letra mono-espaçado buttons.disable_monospace_font=Desabilitar tipo de letra mono-espaçado [filter] +string.asc=A–Z +string.desc=Z–A [error] occurred=Ocorreu um erro @@ -235,6 +253,7 @@ license_desc=Vá buscar documentação antes de alterar quaisquer configurações. require_db_desc=Gitea requer MySQL, PostgreSQL, MSSQL, SQLite3 ou TiDB (protocolo MySQL). @@ -251,10 +270,16 @@ path=Localização sqlite_helper=Localização do ficheiro da base de dados em SQLite3.
Insira um caminho absoluto se corre o Gitea como um serviço. reinstall_error=Está a tentar instalar numa base de dados do Gitea já existente reinstall_confirm_message=Reinstalar com uma base de dados do Gitea já existente pode causar múltiplos problemas. Na maioria dos casos deve usar o seu "app.ini" existente para correr o Gitea. Se souber o que está a fazer, confirme o seguinte: +reinstall_confirm_check_1=Os dados encriptados pela chave secreta (SECRET_KEY) no ficheiro app.ini poderão ser perdidos: os utilizadores poderão não ser capazes de iniciar a sessão com autenticação em dois passos (2FA) ou com chaves de utilização única (OTP) e as réplicas poderão deixar de funcionar adequadamente. Ao marcar esta opção estará a confirmar que o ficheiro app.ini vigente contém a SECRET_KEY certa. +reinstall_confirm_check_2=Os repositórios e as configurações poderão ter de voltar a ser sincronizados. Ao marcar esta opção estará a confirmar que vai voltar a sincronizar manualmente os automatismos para os repositórios e o ficheiro authorized_keys. Estará também a confirmar que vai assegurar que as configurações do repositório e das réplicas estão certas. reinstall_confirm_check_3=Você confirma que tem a certeza absoluta de que este Gitea está a correr com a localização certa do ficheiro app.ini e que tem a certeza de que tem de voltar a instalar. Você confirma que tomou conhecimento dos riscos acima descritos. err_empty_db_path=A localização da base de dados SQLite3 não pode estar vazia. no_admin_and_disable_registration=Não pode desabilitar a auto-inscrição de utilizadores sem criar uma conta de administrador. err_empty_admin_password=A senha do administrador não pode estar em branco. +err_empty_admin_email=O endereço de email do administrador não pode estar em branco. +err_admin_name_is_reserved=O nome de utilizador do administrador é inválido porque está reservado +err_admin_name_pattern_not_allowed=O nome de utilizador do administrador é inválido porque corresponde a um padrão reservado. +err_admin_name_is_invalid=O nome de utilizador do administrador é inválido general_title=Configurações gerais app_name=Título do sítio @@ -270,6 +295,7 @@ domain_helper=Domínio ou endereço do servidor. ssh_port=Porto do servidor SSH ssh_port_helper=O número do porto que o seu servidor SSH usa. Deixe em branco para desabilitar. http_port=Porto de escuta HTTP do Gitea +http_port_helper=O número do porto onde o servidor web do Gitea estará à escuta. app_url=URL base do Gitea app_url_helper=Endereço base para os URLs e notificações por email das clonagens por HTTP(S). log_root_path=Localização dos registos @@ -405,6 +431,8 @@ allow_password_change=Exigir que o utilizador mude a senha (recomendado) reset_password_mail_sent_prompt=Foi enviado um email de confirmação para %s. Verifique a sua caixa de entrada dentro de %s para completar o processo de recuperação. active_your_account=Ponha a sua conta em funcionamento account_activated=A conta foi posta em funcionamento +prohibit_login=Início de sessão proibido +prohibit_login_desc=A sua conta está proibida de iniciar sessão. Contacte o administrador. resent_limit_prompt=Já fez um pedido recentemente para enviar um email para pôr a conta em funcionamento. Espere 3 minutos e tente novamente. has_unconfirmed_mail=Olá %s, tem um endereço de email não confirmado (%s). Se não recebeu um email de confirmação ou precisa de o voltar a enviar, clique no botão abaixo. change_unconfirmed_mail_address=Se o seu endereço de email estiver errado, pode mudá-lo aqui e enviar um novo email de confirmação. @@ -425,6 +453,7 @@ use_scratch_code=Usar um código de recuperação twofa_scratch_used=Você usou o seu código de recuperação. Foi reencaminhado para a página de configurações da autenticação em dois passos para poder remover o registo do seu dispositivo ou gerar um novo código de recuperação. twofa_passcode_incorrect=A senha está errada. Se perdeu o seu dispositivo, use o código de recuperação para iniciar a sessão. twofa_scratch_token_incorrect=O código de recuperação está errado. +twofa_required=Tem de configurar a autenticação em dois passos para obter acesso aos repositórios ou então tentar iniciar a sessão novamente. login_userpass=Iniciar sessão login_openid=OpenID oauth_signup_tab=Fazer inscrição @@ -443,13 +472,17 @@ openid_connect_desc=O URI do OpenID escolhido é desconhecido. Associe-o a uma n openid_register_title=Criar uma conta nova openid_register_desc=O URI do OpenID escolhido é desconhecido. Associe-o a uma nova conta aqui. openid_signin_desc=Insira o seu URI OpenID. Por exemplo: alice.openid.exemplo.org or https://openid.exemplo.org/alice. +disable_forgot_password_mail=A recuperação de conta está desabilitada porque não foi definido um endereço de email. Entre em contacto com o administrador do sítio. +disable_forgot_password_mail_admin=A recuperação de conta só está disponível quando está configurado um endereço de email. email_domain_blacklisted=Não pode fazer um registo com o seu endereço de email. authorize_application=Autorizar aplicação authorize_redirect_notice=Irá ser reencaminhado para %s se autorizar esta aplicação. authorize_application_created_by=Esta aplicação foi criada por %s. +authorize_application_description=Se conceder o acesso, a aplicação terá privilégios para aceder e alterar toda a informação da sua conta, incluindo organizações e repositórios privados. authorize_application_with_scopes=Com âmbitos: %s authorize_title=Autorizar o acesso de "%s" à sua conta? authorization_failed=A autorização falhou +authorization_failed_desc=A autorização falhou porque encontrámos um pedido inválido. Entre em contacto com o responsável pela aplicação que tentou autorizar. sspi_auth_failed=Falhou a autenticação SSPI password_pwned=A senha que escolheu está numa lista de senhas roubadas anteriormente expostas em fugas de dados públicas. Tente novamente com uma senha diferente e considere também mudar esta senha nos outros sítios. password_pwned_err=Não foi possível completar o pedido ao HaveIBeenPwned @@ -513,6 +546,7 @@ release.download.targz=Código fonte (TAR.GZ) repo.transfer.subject_to=%s gostaria de transferir "%s" para %s repo.transfer.subject_to_you=%s gostaria de transferir "%s" para si repo.transfer.to_you=você +repo.transfer.body=Para o aceitar ou rejeitar, visite %s ou ignore-o, simplesmente. repo.collaborator.added.subject=%s adicionou você a %s repo.collaborator.added.text=Foi adicionado(a) como colaborador(a) do repositório: @@ -564,6 +598,7 @@ url_error=`"%s" não é um URL válido.` include_error=` tem que conter o texto "%s".` glob_pattern_error=` o padrão glob é inválido: %s.` regex_pattern_error=` o padrão regex é inválido: %s.` +username_error=` só pode conter caracteres alfanuméricos ('0-9','a-z','A-Z'), hífen ('-'), sublinhado ('_') e ponto ('.') Não pode começar nem terminar com caracteres não alfanuméricos e caracteres não alfanuméricos consecutivos também são proibidos.` invalid_group_team_map_error=` o mapeamento é inválido: %s` unknown_error=Erro desconhecido: captcha_incorrect=O código CAPTCHA está errado. @@ -578,14 +613,17 @@ username_has_not_been_changed=O nome de utilizador não foi modificado repo_name_been_taken=O nome do repositório já foi usado. repository_force_private=Forçar Privado está habilitado: repositórios privados não podem ser tornados públicos. repository_files_already_exist=Já existem ficheiros neste repositório. Contacte o administrador do sistema. +repository_files_already_exist.adopt=Já existem ficheiros neste repositório e só podem ser adoptados. repository_files_already_exist.delete=Já existem ficheiros neste repositório. Tem que os eliminar. repository_files_already_exist.adopt_or_delete=Já existem ficheiros neste repositório. Adopte-os ou elimine-os. visit_rate_limit=Limitação da taxa de visita remota. +2fa_auth_required=A visita remota requer autenticação em dois passos. org_name_been_taken=O nome da organização já foi tomado. team_name_been_taken=O nome da equipa já foi tomado. team_no_units_error=Permitir acesso a pelo menos uma secção do repositório. email_been_used=O endereço de email já está em uso. email_invalid=O endereço de email é inválido. +email_domain_is_not_allowed=O domínio do endereço de email do utilizador %s entra en conflito com o EMAIL_DOMAIN_ALLOWLIST ou com o EMAIL_DOMAIN_BLOCKLIST. Verifique se a operação estava prevista. openid_been_used=O endereço OpenID "%s" já está em uso. username_password_incorrect=O nome de utilizador ou a senha estão errados. password_complexity=A senha não passa nos requisitos de complexidade: @@ -610,8 +648,14 @@ invalid_ssh_key=Não é possível validar a sua chave SSH: %s invalid_gpg_key=Não é possível validar a sua chave GPG: %s invalid_ssh_principal=Protagonista inválido: %s must_use_public_key=A chave que você forneceu é privada. Não carregue a sua chave em lugar nenhum, em vez disso use a sua chave pública. +unable_verify_ssh_key=Não é possível validar a chave SSH. Verifique se tem erros. auth_failed=Falhou a autenticação: %v +still_own_repo=A sua conta possui um ou mais repositórios. Elimine-os ou transfira-os primeiro. +still_has_org=A sua conta é membro de uma ou mais organizações. Saia delas primeiro. +still_own_packages=A sua conta possui um ou mais pacotes. Elimine-os primeiro. +org_still_own_repo=Esta organização ainda possui um ou mais repositórios. Elimine-os ou transfira-os primeiro. +org_still_own_packages=Esta organização ainda possui um ou mais pacotes. Elimine-os primeiro. target_branch_not_exist=O ramo de destino não existe. target_ref_not_exist=A referência de destino não existe %s @@ -642,6 +686,7 @@ settings=Configurações do utilizador form.name_reserved=O nome de utilizador "%s" está reservado. form.name_pattern_not_allowed=O padrão "%s" não é permitido no nome de utilizador. +form.name_chars_not_allowed=O nome de utilizador "%s" contém caracteres inválidos. block.block=Bloquear block.block.user=Bloquear utilizador @@ -658,6 +703,7 @@ block.info_3=enviar-lhe notificações ao @mencionar o seu nome de utilizador block.info_4=convidá-lo/a para ser colaborador/a nos repositórios dele/dela block.info_5=juntar aos favoritos, derivar ou vigiar repositórios block.info_6=abrir e comentar questões ou pedidos de integração +block.info_7=reagir aos seus comentários em questões ou pedidos de integração block.user_to_block=Utilizador a bloquear block.note=Nota block.note.title=Nota opcional: @@ -708,6 +754,7 @@ cancel=Cancelar language=Idioma ui=Tema hidden_comment_types=Tipos de comentários ocultos +hidden_comment_types_description=Os tipos de comentário marcados aqui não serão mostrados nas páginas das questões. Marcar "Rótulo", por exemplo, remove todos os comentários "{utilizador} adicionou/removeu {rótulo}". hidden_comment_types.ref_tooltip=Comentários onde esta questão foi referenciada a partir de outra questão/cometimento/… hidden_comment_types.issue_ref_tooltip=Comentários onde o utilizador altera o ramo/etiqueta associado à questão comment_type_group_reference=Referência @@ -755,12 +802,15 @@ manage_themes=Escolher o tema padrão manage_openid=Gerir endereços OpenID email_desc=O seu endereço de email principal irá ser usado para notificações, recuperação de senha e, desde que não esteja oculto, operações Git baseados na web. theme_desc=Este será o seu tema padrão em todo o sítio. +theme_colorblindness_help=Suporte a temas para daltónicos +theme_colorblindness_prompt=O Gitea apenas tem alguns temas com suporte básico para daltónicos que têm apenas algumas cores definidas. O trabalho ainda está em andamento. Poderiam ser feitos mais melhoramentos se fossem definidas mais cores nos ficheiros CSS do tema. primary=Principal activated=Em uso requires_activation=Tem que ser habilitado primary_email=Tornar no principal activate_email=Enviar pedido de verificação activations_pending=Habilitações pendentes +can_not_add_email_activations_pending=Existe uma validação pendente. Tente de novo dentro de alguns minutos, se quiser adicionar um novo endereço de email. delete_email=Remover email_deletion=Remover endereço de email email_deletion_desc=Este endereço de email e informações relacionadas serão removidos da sua conta. Os cometimentos feitos no Git com este endereço de email permanecerão inalterados. Quer continuar? @@ -806,6 +856,7 @@ gpg_key_matched_identities_long=As identidades incorporadas nesta chave correspo gpg_key_verified=Chave validada gpg_key_verified_long=A chave foi validada com um código e pode ser usada para validar cometimentos que correspondam a qualquer dos endereços de email em uso por parte deste utilizador, para além das identidades correspondentes a esta chave. gpg_key_verify=Validar +gpg_invalid_token_signature=A chave GPG, assinatura ou código fornecidos não correspondem, ou então o código expirou. gpg_token_required=Tem que fornecer uma assinatura para o código abaixo gpg_token=Código gpg_token_help=Pode gerar uma assinatura usando o seguinte comando: @@ -815,6 +866,7 @@ verify_gpg_key_success=A chave GPG "%s" foi validada. ssh_key_verified=Chave validada ssh_key_verified_long=A chave foi validada com um código e pode ser usada para validar cometimentos que correspondam a qualquer dos endereços de email em uso por parte deste utilizador. ssh_key_verify=Validar +ssh_invalid_token_signature=A chave SSH, assinatura ou código fornecidos não correspondem, ou então o código expirou. ssh_token_required=Tem que fornecer uma assinatura para o código abaixo ssh_token=Código ssh_token_help=Pode gerar uma assinatura usando o seguinte comando: @@ -835,6 +887,7 @@ gpg_key_deletion=Remover chave GPG ssh_principal_deletion=Remover Protagonista de Certificado SSH ssh_key_deletion_desc=Remover uma chave SSH revoga o acesso dessa chave à sua conta. Quer continuar? gpg_key_deletion_desc=Remover uma chave GPG retira as validações feitas sobre os cometimentos assinados com ela. Quer continuar? +ssh_principal_deletion_desc=Remover um Protagonista de Certificado SSH revoga o acesso dele à sua conta. Quer continuar? ssh_key_deletion_success=A chave SSH foi removida. gpg_key_deletion_success=A chave GPG foi removida. ssh_principal_deletion_success=O protagonista foi removido. @@ -896,6 +949,7 @@ create_oauth2_application_button=Criar aplicação create_oauth2_application_success=Criou com sucesso uma nova aplicação OAuth2. update_oauth2_application_success=Modificou com sucesso a aplicação OAuth2. oauth2_application_name=Nome da aplicação +oauth2_confidential_client=Cliente confidencial. Escolha esta opção para aplicações que mantêm o segredo confidencial, tais como aplicações web. Não escolha esta opção para aplicações nativas, incluindo aplicações para computador e aplicações móveis. oauth2_skip_secondary_authorization=Saltar a autorização para clientes públicos depois de lhes ceder acesso uma vez. Pode representar um risco de segurança. oauth2_redirect_uris=URIs de reencaminhamento. Use uma linha por URI. save_application=Guardar @@ -910,8 +964,10 @@ oauth2_application_remove_description=A remoção de uma aplicação OAuth2 impe oauth2_application_locked=O Gitea pré-regista algumas aplicações OAuth2 no arranque, se forem habilitadas na configuração. Para evitar comportamentos inesperados, estas não podem ser editadas nem removidas. Consulte a documentação sobre o OAuth2 para obter mais informações. authorized_oauth2_applications=Aplicações OAuth2 autorizadas +authorized_oauth2_applications_description=Concedeu acesso à sua conta pessoal do Gitea a estas aplicações de terceiros. Revogue o acesso às aplicações que já não precisa. revoke_key=Revogar revoke_oauth2_grant=Revogar acesso +revoke_oauth2_grant_description=Revogar o acesso desta aplicação de terceiros impedi-la-á de aceder aos seus dados. Tem a certeza? revoke_oauth2_grant_success=Acesso revogado com sucesso. twofa_desc=Para proteger a sua conta contra o roubo de senhas, pode usar um telemóvel ou outro dispositivo para recerber um código de utilização única baseado no tempo ("TOTP"). @@ -921,6 +977,7 @@ twofa_not_enrolled=A autenticação em dois passos não está neste momento habi twofa_disable=Desabilitar autenticação em dois passos twofa_scratch_token_regenerate=Voltar a gerar o código de recuperação de utilização única twofa_scratch_token_regenerated=O seu código de recuperação de utilização única agora é %s. Guarde-o num lugar seguro, uma vez que nunca mais vai ser mostrado. +twofa_enroll=Habilitar autenticação em dois passos twofa_disable_note=Pode desabilitar a autenticação em dois passos, se for necessário. twofa_disable_desc=Desabilitar a autenticação em dois passos tornará a sua conta menos segura. Quer continuar? regenerate_scratch_token_desc=Se perdeu o seu código de recuperação ou já o usou para iniciar uma sessão, pode restaurá-lo aqui. @@ -936,6 +993,7 @@ webauthn_desc=Chaves de segurança são dispositivos de hardware contendo chaves webauthn_register_key=Adicionar chave de segurança webauthn_nickname=Apelido webauthn_delete_key=Remover chave de segurança +webauthn_delete_key_desc=Se remover uma chave de segurança, deixará de poder usá-la para iniciar a sessão. Quer continuar? webauthn_key_loss_warning=Se perder as suas chaves de segurança, perderá acesso à sua conta. webauthn_alternative_tip=Poderá querer configurar um método de autenticação adicional. @@ -1052,6 +1110,7 @@ mirror_address_protocol_invalid=O URL fornecido é inválido. Só se pode replic mirror_lfs=Armazenamento de Ficheiros Grandes (LFS) mirror_lfs_desc=Habilitar a réplica de dados LFS. mirror_lfs_endpoint=Destino LFS +mirror_lfs_endpoint_desc=A sincronização irá tentar usar o URL de clonagem para determinar o servidor LFS. Também pode especificar um destino personalizado se os dados do repositório LFS forem armazenados noutro lugar. mirror_last_synced=Última sincronização mirror_password_placeholder=(inalterada) mirror_password_blank_placeholder=(não definida) @@ -1064,6 +1123,7 @@ stars=Favoritos reactions_more=e mais %d unit_disabled=O administrador desabilitou esta secção do repositório. language_other=Outros +adopt_search=Insira o nome de utilizador para procurar repositórios adoptados… (deixe em branco para encontrar todos) adopt_preexisting_label=Adoptar ficheiros adopt_preexisting=Adoptar ficheiros pré-existentes adopt_preexisting_content=Criar repositório a partir de %s @@ -1105,6 +1165,8 @@ template.issue_labels=Rótulos das questões template.one_item=Tem que escolher pelo menos um item do modelo template.invalid=Tem que escolher um repositório modelo +archive.title=Este repositório está arquivado. Pode ver os seus ficheiros e cloná-lo. Não pode lançar questões nem fazer pedidos de integração nem fazer envios. +archive.title_date=Este repositório foi arquivado em %s. Pode ver os ficheiros e cloná-lo. Não pode abrir questões nem fazer pedidos de integração nem enviar cometimentos. archive.issue.nocomment=Este repositório está arquivado. Não pode comentar nas questões. archive.pull.nocomment=Este repositório está arquivado. Não pode comentar nos pedidos de integração. @@ -1121,6 +1183,7 @@ migrate_options_lfs=Migrar ficheiros LFS migrate_options_lfs_endpoint.label=Destino LFS migrate_options_lfs_endpoint.description=A migração irá tentar usar o seu controlo remoto do Git para determinar o servidor LFS. Também pode especificar um destino personalizado se os dados do repositório LFS forem armazenados noutro lugar. migrate_options_lfs_endpoint.description.local=Uma localização de servidor local também é suportada. +migrate_options_lfs_endpoint.placeholder=Se for deixado em branco, o destino será determinado a partir do URL do clone. migrate_items=Itens da migração migrate_items_wiki=Wiki migrate_items_milestones=Etapas @@ -1132,8 +1195,10 @@ migrate_items_releases=Lançamentos migrate_repo=Migrar o repositório migrate.clone_address=Migrar / clonar a partir do URL migrate.clone_address_desc=O URL de clonagem HTTP(S) ou Git de um repositório existente +migrate.github_token_desc=Pode colocar aqui um ou mais códigos, separados por vírgulas, para tornar mais rápida a migração, para compensar a limitação de velocidade da API do GitHub. AVISO: O abuso desta funcionalidade poderá violar a política do seu fornecedor de serviço e levar ao bloqueio da(s) sua(a) conta(s). migrate.clone_local_path=ou uma localização no servidor local migrate.permission_denied=Não está autorizado a importar repositórios locais. +migrate.permission_denied_blocked=Não pode importar de servidores não permitidos. Peça ao administrador para verificar as configurações ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS. migrate.invalid_local_path=A localização local é inválida. Não existe ou não é uma pasta. migrate.invalid_lfs_endpoint=O destino LFS não é válido. migrate.failed=A migração falhou: %v @@ -1141,6 +1206,7 @@ migrate.migrate_items_options=É necessário um código de acesso para migrar it migrated_from=Migrado de %[2]s migrated_from_fake=Migrado de %[1]s migrate.migrate=Migrar de %s +migrate.migrating=Migrando a partir de %s… migrate.migrating_failed=A migração de %s falhou. migrate.migrating_failed.error=Falhou a migração: %s migrate.migrating_failed_no_addr=A migração falhou. @@ -1189,6 +1255,7 @@ clone_this_repo=Clonar este repositório cite_this_repo=Citar este repositório create_new_repo_command=Criando um novo repositório na linha de comandos push_exist_repo=Enviando, pela linha de comandos, um repositório existente +empty_message=Este repositório não tem qualquer conteúdo. broken_message=Os dados Git subjacentes a este repositório não podem ser lidos. Contacte o administrador desta instância ou elimine este repositório. no_branch=Este repositório não tem quaisquer ramos. @@ -1207,6 +1274,7 @@ projects=Planeamentos packages=Pacotes actions=Operações labels=Rótulos +org_labels_desc=Rótulos ao nível da organização que podem ser usados em todos os repositórios desta organização org_labels_desc_manage=gerir milestone=Etapa @@ -1255,6 +1323,7 @@ commit_graph.color=Colorido commit.contained_in=Este cometimento está contido em: commit.contained_in_default_branch=Este cometimento é parte do ramo principal commit.load_referencing_branches_and_tags=Carregar ramos e etiquetas que referenciem este cometimento +commit.merged_in_pr=Este cometimento foi integrado dentro do pedido de integração %s. blame=Responsabilidade download_file=Descarregar ficheiro normal_view=Vista normal @@ -1303,13 +1372,17 @@ editor.new_branch_name_desc=Nome do novo ramo… editor.cancel=Cancelar editor.filename_cannot_be_empty=O nome do ficheiro não pode estar em branco. editor.filename_is_invalid=O nome do ficheiro é inválido: "%s". +editor.commit_email=Endereço de email do cometimento +editor.invalid_commit_email=O endereço de email do comentimento é inválido. editor.branch_does_not_exist=O ramo "%s" não existe neste repositório. editor.branch_already_exists=O ramo "%s" já existe neste repositório. editor.directory_is_a_file=O nome da pasta "%s" já é usado como um nome de ficheiro neste repositório. +editor.file_is_a_symlink=`"%s" é uma ligação simbólica. Ligações simbólicas não podem ser editadas no editor web.` editor.filename_is_a_directory=O nome de ficheiro "%s" já está a ser usado como um nome de pasta neste repositório. editor.file_modifying_no_longer_exists=O ficheiro que está a ser modificado, "%s", já não existe neste repositório. editor.file_changed_while_editing=O conteúdo do ficheiro mudou desde que começou a editar. Clique aqui para ver as modificações ou clique em Cometer novamente para escrever por cima. editor.file_already_exists=Já existe um ficheiro com o nome "%s" neste repositório. +editor.commit_id_not_matching=O ID do cometimento não corresponde ao ID de quando começou a editar. Faça o cometimento para um ramo de remendo (patch) e depois faça a integração. editor.push_out_of_date=O envio parece estar obsoleto. editor.commit_empty_file_header=Cometer um ficheiro vazio editor.commit_empty_file_text=O ficheiro que está prestes a cometer está vazio. Quer continuar? @@ -1335,6 +1408,7 @@ editor.fork_create_description=Não pode editar este repositório. Ao invés dis editor.fork_edit_description=Não pode editar este repositório. As modificações irão ser escritas na sua derivação %s, para que possa criar um pedido de integração. editor.fork_not_editable=Fez uma derivação deste repositório, mas a sua derivação não é editável. editor.fork_failed_to_push_branch=Falhou ao enviar o ramo %s para o seu repositório. +editor.fork_branch_exists=O ramo "%s" já existe na sua derivação. Escolha outro nome para o ramo. commits.desc=Navegar pelo histórico de modificações no código fonte. commits.commits=Cometimentos @@ -1436,6 +1510,7 @@ issues.new.clear_assignees=Retirar todos os encarregados issues.new.no_assignees=Sem encarregados issues.new.no_reviewers=Sem revisores issues.new.blocked_user=Não pode criar a questão porque foi bloqueado/a pelo/a proprietário/a do repositório. +issues.edit.already_changed=Não foi possível guardar as modificações da questão. O conteúdo parece ter sido modificado por outro utilizador, entretanto. Refresque a página e tente editar de novo para evitar sobrepor as modificações dele. issues.edit.blocked_user=Não pode editar o conteúdo porque foi bloqueado/a pelo/a remetente ou pelo/a proprietário/a do repositório. issues.choose.get_started=Começar issues.choose.open_external_link=Abrir @@ -1507,6 +1582,7 @@ issues.filter_type.reviewed_by_you=Revistos por si issues.filter_sort=Ordem issues.filter_sort.latest=Mais recentes issues.filter_sort.oldest=Mais antigas +issues.filter_sort.recentupdate=Modificadas recentemente issues.filter_sort.leastupdate=Modificadas há muito tempo issues.filter_sort.mostcomment=Mais comentadas issues.filter_sort.leastcomment=Menos comentadas @@ -1706,7 +1782,9 @@ issues.dependency.pr_closing_blockedby=O encerramento deste pedido de integraç issues.dependency.issue_closing_blockedby=O encerramento desta questão está bloqueado pelas seguintes questões issues.dependency.issue_close_blocks=Esta questão bloqueia o encerramento das seguintes questões issues.dependency.pr_close_blocks=Este pedido de integração bloqueia o encerramento das seguintes questões +issues.dependency.issue_close_blocked=Tem que encerrar todas as questões que bloqueiam esta questão antes de a poder encerrar. issues.dependency.issue_batch_close_blocked=Não é possível fechar em lote as questões que escolheu porque a questão #%d ainda tem dependências em aberto +issues.dependency.pr_close_blocked=Tem que encerrar todas as questões que bloqueiam este pedido de integração antes de poder proceder à integração. issues.dependency.blocks_short=Bloqueia issues.dependency.blocked_by_short=Depende de issues.dependency.remove_header=Remover dependência @@ -1717,11 +1795,13 @@ issues.dependency.add_error_same_issue=Não pode fazer uma questão depender de issues.dependency.add_error_dep_issue_not_exist=A questão dependente não existe. issues.dependency.add_error_dep_not_exist=A dependência não existe. issues.dependency.add_error_dep_exists=A dependência já existe. +issues.dependency.add_error_cannot_create_circular=Não pode criar uma dependência com duas questões em que cada uma bloqueia a outra. issues.dependency.add_error_dep_not_same_repo=Ambas as questões têm que estar no mesmo repositório. issues.review.self.approval=Não pode aprovar o seu próprio pedido de integração. issues.review.self.rejection=Não pode solicitar modificações sobre o seu próprio pedido de integração. issues.review.approve=aprovou estas modificações %s issues.review.comment=reviu %s +issues.review.dismissed=descartou a revisão de %s %s issues.review.dismissed_label=Descartada issues.review.left_comment=deixou um comentário issues.review.content.empty=Tem que deixar um comentário indicando a(s) modificação(ões) solicitada(s). @@ -1729,6 +1809,7 @@ issues.review.reject=modificações solicitadas %s issues.review.wait=foi solicitada para revisão %s issues.review.add_review_request=solicitou revisão de %s %s issues.review.remove_review_request=removeu a solicitação de revisão para %s %s +issues.review.remove_review_request_self=recusou rever %s issues.review.pending=Pendente issues.review.pending.tooltip=Este comentário não está visível para os outros utilizadores, neste momento. Para submeter os seus comentários pendentes, escolha "%s" → "%s/%s/%s" no topo da página. issues.review.review=Revisão @@ -1750,6 +1831,7 @@ issues.review.requested=Revisão pendente issues.review.rejected=Modificações solicitadas issues.review.stale=Modificada depois da aprovação issues.review.unofficial=Aprovação não oficial +issues.assignee.error=Nem todos os encarregados foram adicionados, devido a um erro inesperado. issues.reference_issue.body=Conteúdo issues.content_history.deleted=eliminado issues.content_history.edited=editado @@ -1766,6 +1848,7 @@ pulls.desc=Habilitar pedidos de integração e revisão de código-fonte. pulls.new=Novo pedido de integração pulls.new.blocked_user=Não pode criar o pedido de integração porque foi bloqueado/a pelo/a proprietário/a do repositório. pulls.new.must_collaborator=Tem de ser um/a colaborador/a para criar um pedido de integração. +pulls.edit.already_changed=Não foi possível guardar as modificações do pedido de integração. O conteúdo parece ter sido modificado por outro utilizador, entretanto. Refresque a página e tente editar de novo para evitar sobrepor as modificações dele. pulls.view=Ver pedido de integração pulls.compare_changes=Novo pedido de integração pulls.allow_edits_from_maintainers=Permitir edições por parte dos responsáveis @@ -1786,6 +1869,7 @@ pulls.show_all_commits=Mostrar todos os cometimentos pulls.show_changes_since_your_last_review=Mostrar modificações desde a sua última revisão pulls.showing_only_single_commit=Mostrando apenas as modificações do comentimento %[1]s pulls.showing_specified_commit_range=Mostrando apenas as modificações entre %[1]s..%[2]s +pulls.select_commit_hold_shift_for_range=Escolha o comentimento. Para escolher um intervalo, mantenha premido o shift enquanto clica. pulls.review_only_possible_for_full_diff=A revisão só é possível ao visualizar o diff completo pulls.filter_changes_by_commit=Filtrar por cometimento pulls.nothing_to_compare=Estes ramos são iguais. Não há necessidade de criar um pedido de integração. @@ -1814,6 +1898,7 @@ pulls.add_prefix=Adicione o prefixo %s pulls.remove_prefix=Remover o prefixo %s pulls.data_broken=Este pedido de integração está danificado devido à falta de informação da derivação. pulls.files_conflicted=Este pedido de integração contém modificações que entram em conflito com o ramo de destino. +pulls.is_checking=Verificando se existem conflitos na integração… pulls.is_ancestor=Este ramo já está incluído no ramo de destino. Não há nada a integrar. pulls.is_empty=As modificações feitas neste ramo já existem no ramo de destino. Este cometimento ficará vazio. pulls.required_status_check_failed=Algumas das verificações obrigatórias não foram bem sucedidas. @@ -1837,12 +1922,16 @@ pulls.reject_count_1=%d pedido de modificação pulls.reject_count_n=%d pedidos de modificação pulls.waiting_count_1=%d revisão pendente pulls.waiting_count_n=%d revisões pendentes +pulls.wrong_commit_id=ID do cometimento tem que ser um ID de cometimento no ramo de destino pulls.no_merge_desc=A integração constante neste pedido não pode ser executada porque todas as opções de integração do repositório estão desabilitadas. pulls.no_merge_helper=Habilite as opções de integração nas configurações do repositório ou faça a integração manualmente. pulls.no_merge_wip=A integração constante neste pedido não pode ser executada porque está marcada como sendo trabalho em andamento. +pulls.no_merge_not_ready=A integração constante neste pedido não pode ser executada. Verifique o estado da revisão e as verificações de estado. pulls.no_merge_access=Não tem autorização para executar a integração constante neste pedido. pulls.merge_pull_request=Criar um cometimento de integração +pulls.rebase_merge_pull_request=Mudar a base e avançar rapidamente +pulls.rebase_merge_commit_pull_request=Mudar a base e criar um cometimento de integração pulls.squash_merge_pull_request=Criar cometimento de compactação pulls.fast_forward_only_merge_pull_request=Avançar rapidamente apenas pulls.merge_manually=Integrar manualmente @@ -1850,10 +1939,17 @@ pulls.merge_commit_id=O ID de cometimento da integração pulls.require_signed_wont_sign=O ramo requer que os cometimentos sejam assinados mas esta integração não vai ser assinada pulls.invalid_merge_option=Não pode usar esta opção de integração neste pedido de integração. +pulls.merge_conflict=A integração falhou: Houve um conflito durante a integração. Dica: Tente uma estratégia diferente. pulls.merge_conflict_summary=Mensagem de erro +pulls.rebase_conflict=A integração falhou: Houve um conflito durante a mudança de base do cometimento %[1]s. Dica: Tente uma estratégia diferente. pulls.rebase_conflict_summary=Mensagem de erro +pulls.unrelated_histories=A integração falhou: O topo da integração e a base não partilham um histórico comum. Dica: Tente uma estratégia diferente. +pulls.merge_out_of_date=Falhou a integração: Enquanto gerava a integração, a base foi modificada. Dica: Tente de novo. +pulls.head_out_of_date=Falhou a integração: Enquanto gerava a integração, o topo foi modificado. Dica: Tente de novo. +pulls.has_merged=Falhou: A integração constante do pedido foi executada. Não pode integrar novamente nem modificar o ramo alvo. pulls.push_rejected=O envio falhou: O envio foi rejeitado. Reveja os Automatismos do Git neste repositório. pulls.push_rejected_summary=Mensagem completa de rejeição +pulls.push_rejected_no_message=O envio falhou: O envio foi rejeitado mas não houve qualquer mensagem remota. Reveja os Automatismos do Git para este repositório. pulls.open_unmerged_pull_exists=`Não pode executar uma operação de reabertura porque há um pedido de integração pendente (#%d) com propriedades idênticas.` pulls.status_checking=Algumas verificações estão pendentes pulls.status_checks_success=Todas as verificações foram bem sucedidas @@ -1879,6 +1975,7 @@ pulls.cmd_instruction_merge_title=Integrar pulls.cmd_instruction_merge_desc=Integrar as modificações e enviar para o Gitea. pulls.cmd_instruction_merge_warning=Aviso: Esta operação não pode executar pedidos de integração porque a opção "auto-identificar integração manual" não está habilitada. pulls.clear_merge_message=Apagar mensagem de integração +pulls.clear_merge_message_hint=Apagar a mensagem de integração apenas remove o conteúdo da mensagem de cometimento e mantém os rodapés gerados pelo git, tais como "Co-Autorado-Por…". pulls.auto_merge_button_when_succeed=(quando as verificações forem bem-sucedidas) pulls.auto_merge_when_succeed=Integrar automaticamente quando todas as verificações forem bem-sucedidas @@ -1944,6 +2041,7 @@ signing.wont_sign.nokey=Não existe qualquer chave disponível para assinar este signing.wont_sign.never=Os cometimentos nunca são assinados. signing.wont_sign.always=Os cometimentos são sempre assinados. signing.wont_sign.pubkey=O cometimento não será assinado porque não tem uma chave pública associada à sua conta. +signing.wont_sign.twofa=Tem que ter a autenticação em dois passos habilitada para ter cometimentos assinados. signing.wont_sign.parentsigned=O cometimento não pode ser assinado, uma vez que o anterior também não está. signing.wont_sign.basesigned=A integração não irá ser assinada, uma vez que o cometimento base não foi assinado. signing.wont_sign.headsigned=A integração não irá ser assinada, uma vez que o cometimento de topo não foi assinado. @@ -2057,11 +2155,13 @@ contributors.contribution_type.additions=Adições contributors.contribution_type.deletions=Eliminações settings=Configurações +settings.desc=Configurações é onde pode gerir as configurações do repositório. settings.options=Repositório settings.public_access=Acesso público settings.public_access_desc=Configurar as permissões de acesso público do visitante para substituir os valores predefinidos deste repositório. settings.public_access.docs.not_set=Não definido: nenhuma permissão extra de acesso público. As permissões do visitante seguem a visibilidade e as permissões de membro do repositório. settings.public_access.docs.anonymous_read=Leitura anónima: utilizadores sem sessão iniciada podem consultar a unidade. +settings.public_access.docs.everyone_read=Leitura pública: todos os utilizadores com sessão iniciada podem aceder à unidade com permissão de leitura. Permissão de leitura das unidades de questões / pedidos de integração também significa que os utilizadores podem criar novas questões / pedidos de integração. settings.public_access.docs.everyone_write=Escrita pública: Todos os utilizadores com sessão iniciada têm permissão de escrita na unidade. Apenas a unidade Wiki suporta esta permissão. settings.collaboration=Colaboradores settings.collaboration.admin=Administrador @@ -2079,6 +2179,7 @@ settings.mirror_settings.docs.disabled_pull_mirror.instructions=Configure o seu settings.mirror_settings.docs.disabled_push_mirror.instructions=Configure os seu planeamento para puxar, automaticamente, cometimentos, etiquetas e ramos a partir de outro repositório. settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=Neste momento isto só pode ser feito no menu "Nova migração". Para obter mais informação, consulte: settings.mirror_settings.docs.disabled_push_mirror.info=As réplicas foram desabilitadas pelo administrador deste sítio. +settings.mirror_settings.docs.no_new_mirrors=O seu repositório está a replicar modificações para, ou a partir de, outro repositório. Tenha em mente que neste momento não pode criar novas réplicas. settings.mirror_settings.docs.can_still_use=Embora não possa modificar réplicas existentes ou criar novas, ainda pode usar a sua réplica existente. settings.mirror_settings.docs.pull_mirror_instructions=Para configurar uma réplica de outro repositório, consulte settings.mirror_settings.docs.more_information_if_disabled=Pode aprender mais sobre réplicas de envios e de puxadas aqui: @@ -2153,6 +2254,7 @@ settings.admin_indexer_commit_sha=Último SHA indexado settings.admin_indexer_unindexed=Não indexado settings.reindex_button=Adicionar à fila de reindexação settings.reindex_requested=Reindexação solicitada +settings.admin_enable_close_issues_via_commit_in_any_branch=Fechar uma questão através de um cometimento feito num ramo que não seja o principal settings.danger_zone=Zona de perigo settings.new_owner_has_same_repo=O novo dono já tem um repositório com o mesmo nome. Por favor, escolha outro nome. settings.convert=Converter para um repositório normal @@ -2174,6 +2276,7 @@ settings.transfer_abort_invalid=Não pode cancelar a transferência de um reposi settings.transfer_abort_success=A transferência de repositório para %s foi cancelada com sucesso. settings.transfer_desc=Transferir este repositório para um utilizador ou para uma organização na qual você tenha direitos de administrador. settings.transfer_form_title=Insira o nome do repositório para confirmar: +settings.transfer_in_progress=Está a ser feita uma transferência. Cancele-a, por favor, se quiser transferir este repositório para outro utilizador. settings.transfer_notices_1=- Você perderá o acesso ao repositório se o transferir para um utilizador individual. settings.transfer_notices_2=- Você manterá o acesso ao repositório se o transferir para uma organização da qual você é (co-)proprietário(a). settings.transfer_notices_3=- Se o repositório for privado e for transferido para um utilizador individual, esta operação certifica que o utilizador tem pelo menos a permissão de leitura (e altera as permissões se for necessário). @@ -2188,9 +2291,13 @@ settings.trust_model.default=Modelo de confiança padrão settings.trust_model.default.desc=Usar o modelo de confiança padrão do repositório para esta instalação. settings.trust_model.collaborator=Colaborador settings.trust_model.collaborator.long=Colaborador: Confiar nas assinaturas dos colaboradores +settings.trust_model.collaborator.desc=Assinaturas válidas dos colaboradores deste repositório serão marcadas como "fiável", independentemente de corresponderem, ou não, ao autor do cometimento. Caso contrário, assinaturas válidas serão marcadas como "não fiável" se a assinatura corresponder ao autor do cometimento e "não corresponde", se não corresponder. settings.trust_model.committer=Autor do cometimento +settings.trust_model.committer.long=Autor do cometimento: Confiar nas assinaturas que correspondam aos autores dos cometimentos. Isto corresponde ao comportamento do GitHub e força a que os cometimentos assinados do Gitea tenham o Gitea como autor do cometimento. +settings.trust_model.committer.desc=Assinaturas válidas apenas serão marcadas como "fiável" se corresponderem ao autor do cometimento, caso contrário serão marcadas como "não corresponde". Isto irá forçar o Gitea a ser o autor do cometimento nos cometimentos assinados, ficando o autor real marcado como "Co-autorado-por:" e "Co-cometido-por:" no rodapé do cometimento. A chave padrão do Gitea tem que corresponder a um utilizador na base de dados. settings.trust_model.collaboratorcommitter=Colaborador + Autor do cometimento settings.trust_model.collaboratorcommitter.long=Colaborador + Autor do cometimento: Confiar nas assinaturas dos colaboradores que correspondam ao autor do cometimento +settings.trust_model.collaboratorcommitter.desc=Assinaturas válidas feitas por colaboradores deste repositório serão marcadas como "fiável" se corresponderem ao autor do cometimento. Caso contrário, assinaturas válidas serão marcadas como "não fiável" se a assinatura corresponder ao autor do cometimento e "não corresponde" se não corresponder. Isto irá forçar a que o Gitea seja marcado como sendo o autor do cometimento nos cometimentos assinados, ficando o autor real marcado como "Co-autorado-por:" e "Co-cometido-por:" no rodapé do cometimento. A chave padrão do Gitea tem que corresponder a um utilizador na base de dados. settings.wiki_delete=Eliminar dados do wiki settings.wiki_delete_desc=Eliminar os dados do repositório do wiki é permanente e não pode ser revertido. settings.wiki_delete_notices_1=- Isso excluirá e desabilitará permanentemente o wiki do repositório para %s. @@ -2199,6 +2306,7 @@ settings.wiki_deletion_success=Os dados do repositório do wiki foram eliminados settings.delete=Eliminar este repositório settings.delete_desc=Eliminar um repositório é permanente e não pode ser revertido. settings.delete_notices_1=- Esta operação NÃO PODERÁ ser revertida. +settings.delete_notices_2=- Esta operação eliminará permanentemente o repositório %s, incluindo código-fonte, questões, comentários, dados do wiki e configurações dos colaboradores. settings.delete_notices_fork_1=- Derivações deste repositório tornar-se-ão independentes, após a eliminação. settings.deletion_success=O repositório foi eliminado. settings.update_settings_success=As configurações do repositório foram modificadas. @@ -2220,6 +2328,8 @@ settings.team_not_in_organization=A equipa não está na mesma organização que settings.teams=Equipas settings.add_team=Adicionar equipa settings.add_team_duplicate=A equipa já tem o repositório +settings.add_team_success=A equipa agora tem acesso ao repositório. +settings.change_team_permission_tip=A permissão da equipa é definida na página de configurações da equipa e não pode ter modificações específicas de cada repositório settings.delete_team_tip=Esta equipa tem acesso a todos os repositórios e não pode ser removida settings.remove_team_success=O acesso da equipa ao repositório foi removido. settings.add_webhook=Adicionar automatismo web @@ -2484,6 +2594,7 @@ settings.archive.tagsettings_unavailable=As configurações sobre etiquetas não settings.archive.mirrors_unavailable=As réplicas não estão disponíveis se o repositório estiver arquivado. settings.unarchive.button=Desarquivar repositório settings.unarchive.header=Desarquivar este repositório +settings.unarchive.text=Desarquivar o repositório irá restaurar a capacidade de receber cometimentos e envios, assim como novas questões e pedidos de integração. settings.unarchive.success=O repositório foi desarquivado com sucesso. settings.unarchive.error=Ocorreu um erro enquanto decorria o processo de desarquivar o repositório. Veja os registos para obter mais detalhes. settings.update_avatar_success=O avatar do repositório foi modificado. @@ -2501,9 +2612,11 @@ settings.lfs_invalid_locking_path=Localização inválida: %s settings.lfs_invalid_lock_directory=Não foi possível bloquear a pasta: %s settings.lfs_lock_already_exists=Já existe um bloqueio: %s settings.lfs_lock=Bloquear +settings.lfs_lock_path=Localização do ficheiro a bloquear… settings.lfs_locks_no_locks=Sem bloqueios settings.lfs_lock_file_no_exist=O ficheiro bloqueado não existe no ramo principal settings.lfs_force_unlock=Forçar desbloqueio +settings.lfs_pointers.found=Encontrado(s) %d ponteiro(s) de blob — %d associado(a), %d desassociado(a) (%d ausente do armazenamento) settings.lfs_pointers.sha=SHA do blob settings.lfs_pointers.oid=OID settings.lfs_pointers.inRepo=No repositório @@ -2661,6 +2774,7 @@ branch.new_branch_from=`Criar um novo ramo a partir do ramo "%s"` branch.renamed=O ramo %s foi renomeado para %s. branch.rename_default_or_protected_branch_error=Só os administradores é que podem renomear o ramo principal ou ramos protegidos. branch.rename_protected_branch_failed=Este ramo está protegido por regras de salvaguarda baseadas em padrões glob. +branch.commits_divergence_from=Divergência nos cometimentos: %[1]d atrás e %[2]d à frente de %[3]s branch.commits_no_divergence=Idêntico ao ramo %[1]s tag.create_tag=Criar etiqueta %s @@ -2685,6 +2799,7 @@ error.csv.invalid_field_count=Não é possível apresentar este ficheiro porque error.broken_git_hook=Os automatismos git deste repositório parecem estar danificados. Consulte a documentação sobre como os consertar e depois envie alguns cometimentos para refrescar o estado. [graphs] +component_loading=A carregar %s… component_loading_failed=Não foi possível carregar %s component_loading_info=Isto pode demorar um pouco… component_failed_to_load=Ocorreu um erro inesperado. @@ -2723,11 +2838,17 @@ form.create_org_not_allowed=Não tem permissão para criar uma organização. settings=Configurações settings.options=Organização settings.full_name=Nome completo +settings.email=Endereço de email de contacto settings.website=Sítio web settings.location=Localização settings.permission=Permissões settings.repoadminchangeteam=O administrador do repositório pode adicionar e remover o acesso às equipas settings.visibility=Visibilidade +settings.change_visibility=Alterar visibilidade +settings.change_visibility_notices_1=Se a organização for convertida em privada, a contagem de favoritos do repositório será eliminada e não poderá ser restaurada. +settings.change_visibility_notices_2=Os não-membros irão perder acesso aos repositórios da organização se a visibilidade for mudada para privada. +settings.change_visibility_success=A visibilidade da organização %s foi mudada com sucesso. +settings.visibility_desc=Mudar quem pode ver a organização e os seus repositórios. settings.visibility.public=Público settings.visibility.limited=Limitada (visível apenas para utilizadores autenticados) settings.visibility.limited_shortname=Limitada @@ -2739,7 +2860,10 @@ settings.update_setting_success=As configurações da organização foram modifi settings.rename=Renomear organização settings.rename_desc=Mudar o nome da organização também irá mudar o URL da organização e libertar o nome antigo. +settings.rename_success=A organização %[1]s foi renomeada para %[2]s com sucesso. +settings.rename_no_change=O nome da organização não foi alterado. settings.rename_new_org_name=Novo nome da organização +settings.rename_failed=A renomeação da organização falhou por causa de um erro interno settings.rename_notices_1=Esta operação NÃO PODERÁ ser revertida. settings.rename_notices_2=O antigo nome, enquanto não for reivindicado, irá reencaminhar para o novo. @@ -2749,9 +2873,11 @@ settings.delete_account=Eliminar esta organização settings.delete_prompt=A organização será removida permanentemente. Essa operação NÃO PODERÁ ser revertida! settings.name_confirm=Insira o nome da organização para confirmar: settings.delete_notices_1=Esta operação NÃO PODERÁ ser revertida. +settings.delete_notices_2=Esta operação irá eliminar de forma permanente todos os repositórios de %s, incluindo código-fonte, questões, comentários, dados do wiki e configurações dos colaboradores. settings.delete_notices_3=Esta operação irá eliminar de forma permanente todos os pacotes de %s. settings.delete_notices_4=Esta operação irá eliminar de forma permanente todos os planeamentos de %s. settings.confirm_delete_account=Confirme a eliminação +settings.delete_failed=A eliminação da organização falhou por causa de um erro interno settings.delete_successful=A organização %s foi eliminada com sucesso. settings.hooks_desc=Adicionar automatismos web que serão despoletados para todos os repositórios desta organização. @@ -2808,6 +2934,7 @@ teams.remove_all_repos_title=Remover todos os repositórios da equipa teams.remove_all_repos_desc=Isto irá remover todos os repositórios da equipa. teams.add_all_repos_title=Adicionar todos os repositórios teams.add_all_repos_desc=Isto irá adicionar todos os repositórios da organização à equipa. +teams.add_nonexistent_repo=O repositório que está a tentar adicionar não existe. Crie-o primeiro. teams.add_duplicate_users=O utilizador já é um membro da equipa. teams.repos.none=Não há repositórios que possam ser acedidos por esta equipa. teams.members.none=Não há membros nesta equipa. @@ -2848,6 +2975,7 @@ repositories=Repositórios hooks=Automatismos web integrations=Integrações authentication=Fontes de autenticação +emails=Endereços de email do utilizador config=Configuração config_summary=Resumo config_settings=Configurações @@ -2879,8 +3007,11 @@ dashboard.cron.cancelled=Cron: %[1]s cancelado: %[3]s dashboard.cron.error=Erro no cron: %s: %[3]s dashboard.cron.finished=Cron: %[1]s concluído dashboard.delete_inactive_accounts=Eliminar todas as contas que não tenham sido habilitadas +dashboard.delete_inactive_accounts.started=Foi iniciada a eliminação de todas as contas que não foram habilitadas. dashboard.delete_repo_archives=Eliminar todos os arquivos dos repositórios (ZIP, TAR.GZ, etc) +dashboard.delete_repo_archives.started=Foi iniciada a tarefa de eliminação de todos os repositórios arquivados. dashboard.delete_missing_repos=Eliminar todos os repositórios que não tenham os seus ficheiros Git +dashboard.delete_missing_repos.started=Foi iniciada a tarefa de eliminação de todos os repositórios que não têm ficheiros git. dashboard.delete_generated_repository_avatars=Eliminar avatares gerados do repositório dashboard.sync_repo_branches=Sincronizar ramos perdidos de dados do git para bases de dados dashboard.sync_repo_tags=Sincronizar etiquetas dos dados do git para a base de dados @@ -2888,7 +3019,12 @@ dashboard.update_mirrors=Sincronizar réplicas dashboard.repo_health_check=Verificar a saúde de todos os repositórios dashboard.check_repo_stats=Verificar as estatísticas de todos os repositórios dashboard.archive_cleanup=Eliminar arquivos de repositórios antigos +dashboard.deleted_branches_cleanup=Limpar ramos eliminados dashboard.update_migration_poster_id=Sincronizar os IDs do remetente da migração +dashboard.git_gc_repos=Fazer a recolha do lixo em todos os repositórios +dashboard.resync_all_sshkeys=Sincronizar o ficheiro '.ssh/authorized_keys' com as chaves SSH do Gitea +dashboard.resync_all_sshprincipals=Modificar o ficheiro '.ssh/authorized_principals' com os protagonistas SSH do Gitea +dashboard.resync_all_hooks=Voltar a sincronizar automatismos de pré-acolhimento, modificação e pós-acolhimento de todos os repositórios dashboard.reinit_missing_repos=Reinicializar todos os repositórios Git em falta para os quais existam registos dashboard.sync_external_users=Sincronizar dados externos do utilizador dashboard.cleanup_hook_task_table=Limpar a tabela hook_task @@ -2924,8 +3060,10 @@ dashboard.total_gc_pause=Pausa total da recolha de lixo dashboard.last_gc_pause=Última pausa da recolha de lixo dashboard.gc_times=N.º de recolhas de lixo dashboard.delete_old_actions=Eliminar todo o trabalho antigo da base de dados +dashboard.delete_old_actions.started=Foi iniciado o processo de eliminação de todo o trabalho antigo da base de dados dashboard.update_checker=Verificador de novas versões dashboard.delete_old_system_notices=Eliminar todas as notificações do sistema antigas da base de dados +dashboard.gc_lfs=Recolher lixo dos meta-elementos LFS dashboard.stop_zombie_tasks=Parar tarefas zombie das operações dashboard.stop_endless_tasks=Parar tarefas intermináveis das operações dashboard.cancel_abandoned_jobs=Cancelar trabalhos abandonados das operações @@ -2949,6 +3087,7 @@ users.2fa=Autenticação em dois passos users.repos=Repos. users.created=Criada users.last_login=Último acesso +users.never_login=Nunca acedeu users.send_register_notify=Enviar notificação de registo de utilizador users.new_success=A conta de utilizador "%s" foi criada. users.edit=Editar @@ -2975,6 +3114,7 @@ users.still_own_repo=Este utilizador ainda possui um ou mais repositórios. Elim users.still_has_org=Este utilizador é membro de uma organização. Remova, primeiro, o utilizador de todas as organizações. users.purge=Eliminar utilizador users.purge_help=Eliminar o utilizador à força, juntamente com todos os seus repositórios, organizações e pacotes. Também serão eliminados todos os seus comentários. +users.still_own_packages=Este utilizador ainda possui um ou mais pacotes. Elimine esses pacotes primeiro. users.deletion_success=A conta de utilizador foi eliminada. users.reset_2fa=Reinicializar a autenticação em dois passos users.list_status_filter.menu_text=Filtro @@ -2994,7 +3134,11 @@ users.details=Detalhes do utilizador emails.email_manage_panel=Gestão de endereços de email do utilizador emails.primary=Principal emails.activated=Em uso +emails.filter_sort.email=Endereço de email +emails.filter_sort.email_reverse=Endereço de email (inverso) emails.filter_sort.name=Nome de utilizador +emails.filter_sort.name_reverse=Nome de utilizador (inverso) +emails.updated=Endereço de email modificado emails.not_updated=Falhou a modificação do endereço de email solicitado: %v emails.duplicate_active=Este endereço de email já está a ser usado por outro utilizador. emails.change_email_header=Modificar propriedades do email @@ -3002,6 +3146,7 @@ emails.change_email_text=Tem a certeza que quer modificar este endereço de emai emails.delete=Eliminar email emails.delete_desc=Tem a certeza que quer eliminar este endereço de email? emails.deletion_success=O endereço de email foi eliminado. +emails.delete_primary_email_error=Não pode eliminar o endereço de email principal. orgs.org_manage_panel=Gestão das organizações orgs.name=Nome @@ -3115,20 +3260,29 @@ auths.oauth2_required_claim_name_helper=Defina este nome para restringir o iníc auths.oauth2_required_claim_value=Valor de Reivindicação obrigatório auths.oauth2_required_claim_value_helper=Defina este valor para restringir o início de sessão desta fonte a utilizadores que tenham uma reivindicação com este nome e este valor auths.oauth2_group_claim_name=Reivindicar nome que fornece nomes de grupo para esta fonte. (Opcional) +auths.oauth2_full_name_claim_name=Nome completo reivindicado. (Opcional — se for definido, o nome completo do utilizador será sempre sincronizado com este reivindicado) auths.oauth2_ssh_public_key_claim_name=Nome reivindicado da chave pública SSH +auths.oauth2_admin_group=Valor da Reivindicação de Grupo para utilizadores administradores. (Opcional — exige a reivindicação de nome acima) +auths.oauth2_restricted_group=Valor da Reivindicação de Grupo para utilizadores restritos. (Opcional — exige a reivindicação de nome acima) +auths.oauth2_map_group_to_team=Mapear grupos reclamados em equipas da organização. (Opcional — exige a reivindicação de nome acima) auths.oauth2_map_group_to_team_removal=Remover utilizadores das equipas sincronizadas se esses utilizadores não pertencerem ao grupo correspondente. auths.enable_auto_register=Habilitar o registo automático auths.sspi_auto_create_users=Criar utilizadores automaticamente +auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie, automaticamente, novas contas para utilizadores que iniciam a sessão pela primeira vez auths.sspi_auto_activate_users=Habilitar utilizadores automaticamente auths.sspi_auto_activate_users_helper=Permitir que o método de autenticação SSPI habilite automaticamente os novos utilizadores auths.sspi_strip_domain_names=Remover nomes de domínio dos nomes de utilizador +auths.sspi_strip_domain_names_helper=Se esta opção estiver marcada, os nomes de domínio serão removidos dos nomes do início de sessão (ex.: "DOMÍNIO\utilizador" e "utilizador@exemplo.org" tornar-se-ão "utilizador", simplesmente). auths.sspi_separator_replacement=Separador a usar em vez de \, / e @ +auths.sspi_separator_replacement_helper=O caractere a ser usado para substituir os separadores de nomes de início de sessão de nível inferior (ex.: o \ em "DOMÍNIO\utilizador") e os nomes principais do utilizador (ex.: o @ em "utilizador@exemplo.org"). auths.sspi_default_language=Idioma predefinido do utilizador +auths.sspi_default_language_helper=Idioma predefinido para utilizadores criados automaticamente pelo método de autenticação SSPI. Deixe em branco se preferir que o idioma seja determinado automaticamente. auths.tips=Dicas auths.tips.oauth2.general=Autenticação OAuth2 auths.tips.oauth2.general.tip=Ao registar uma nova autenticação OAuth2, o URL da ligação de retorno ou do reencaminhamento deve ser: auths.tip.oauth2_provider=Fornecedor OAuth2 auths.tip.bitbucket=Registe um novo consumidor de OAuth em %s e adicione a permissão 'Account' - 'Read' +auths.tip.nextcloud=`Registe um novo consumidor OAuth na sua instância usando o seguinte menu "Configurações → Segurança → Cliente OAuth 2.0"` auths.tip.dropbox=Crie uma nova aplicação em %s auths.tip.facebook=`Registe uma nova aplicação em %s e adicione o produto "Facebook Login"` auths.tip.github=Registe uma nova aplicação OAuth em %s @@ -3238,6 +3392,7 @@ config.mailer_sendmail_path=Localização do sendmail config.mailer_sendmail_args=Argumentos extras para o sendmail config.mailer_sendmail_timeout=Tempo limite do Sendmail config.mailer_use_dummy=Fictício +config.test_email_placeholder=Endereço de email (ex.: teste@exemplo.com) config.send_test_mail=Enviar email de teste config.send_test_mail_submit=Enviar config.test_mail_failed=Falhou o envio de um email de teste para "%s": %v @@ -3270,6 +3425,7 @@ config.picture_service=Serviço de imagem config.disable_gravatar=Desabilitar o Gravatar config.enable_federated_avatar=Habilitar avatares federados config.open_with_editor_app_help=Os editores de "Abrir com" do menu de clonagem. Se for deixado em branco, será usado o predefinido. Expanda para ver o predefinido. +config.git_guide_remote_name=Nome remoto do repositório para os comandos git no guia config.git_config=Configuração Git config.git_disable_diff_highlight=Desabilitar o realce de sintaxe no diff @@ -3326,6 +3482,7 @@ monitor.queue.numberinqueue=N.º na fila monitor.queue.review_add=Rever / Adicionar trabalhadores monitor.queue.settings.title=Configurações do agregado monitor.queue.settings.desc=Agregados crescem dinamicamente em resposta aos bloqueios da sua fila de trabalhadores. +monitor.queue.settings.maxnumberworkers=N.º máximo de trabalhadores monitor.queue.settings.maxnumberworkers.placeholder=De momento %[1]d monitor.queue.settings.maxnumberworkers.error=O número máximo de trabalhadores tem que ser um número monitor.queue.settings.submit=Modificar configurações @@ -3351,6 +3508,10 @@ notices.delete_success=As notificações do sistema foram eliminadas. self_check.no_problem_found=Nenhum problema encontrado até agora. self_check.startup_warnings=Alertas do arranque: self_check.database_collation_mismatch=Supor que a base de dados usa a colação: %s +self_check.database_collation_case_insensitive=A base de dados está a usar a colação %s, que é insensível à diferença entre maiúsculas e minúsculas. Embora o Gitea possa trabalhar com ela, pode haver alguns casos raros que não funcionem como esperado. +self_check.database_inconsistent_collation_columns=A base de dados está a usar a colação %s, mas estas colunas estão a usar colações diferentes. Isso poderá causar alguns problemas inesperados. +self_check.database_fix_mysql=Para utilizadores do MySQL/MariaDB, pode usar o comando "gitea doctor convert" para resolver os problemas de colação. Também pode resolver o problema manualmente com comandos SQL "ALTER ... COLLATE ...". +self_check.database_fix_mssql=Para utilizadores do MSSQL só pode resolver o problema manualmente com comandos SQL "ALTER ... COLLATE ...", por enquanto. self_check.location_origin_mismatch=O URL corrente (%[1]s) não corresponde ao URL visto pelo Gitea (%[2]s). Se estiver a usar um reverse proxy, certifique-se que os cabeçalhos "Host" e "X-Forwarded-Proto" estão bem definidos. [action] @@ -3434,6 +3595,8 @@ error.no_committer_account=Não existe qualquer conta ligada ao endereço de ema error.no_gpg_keys_found=Não foi encontrada uma chave conhecida para esta assinatura, na base de dados error.not_signed_commit=Não é um cometimento assinado error.failed_retrieval_gpg_keys=Falhou ao obter uma chave ligada à conta de quem cometeu +error.probable_bad_signature=AVISO! Embora exista uma chave com este ID na base de dados, ela não valida este cometimento! Este cometimento é SUSPEITO. +error.probable_bad_default_signature=AVISO! Embora a chave padrão tenha este ID, ela não valida este cometimento! Este cometimento é SUSPEITO. [units] unit=Unidade @@ -3472,6 +3635,7 @@ versions.view_all=Ver todas dependency.id=ID dependency.version=Versão search_in_external_registry=Procurar em %s +alpine.registry=Configure este registo adicionando o URL no seu ficheiro /etc/apk/repositories: alpine.registry.key=Descarregue a chave RSA pública do registo para dentro da pasta /etc/apk/keys/ para verificar a assinatura do índice: alpine.registry.info=Escolha $branch e $repository da lista abaixo. alpine.install=Para instalar o pacote, execute o seguinte comando: @@ -3484,13 +3648,18 @@ arch.install=Sincronizar pacote com pacman: arch.repository=Informação do repositório arch.repository.repositories=Repositórios arch.repository.architectures=Arquitecturas +cargo.registry=Configure este registo no ficheiro de configuração do Cargo (por exemplo: ~/.cargo/config.toml): cargo.install=Para instalar o pacote usando o Cargo, execute o seguinte comando: +chef.registry=Configure este registo no seu ficheiro ~/.chef/config.rb: chef.install=Para instalar o pacote, execute o seguinte comando: +composer.registry=Configure este registo no seu ficheiro ~/.composer/config.json: composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando: composer.dependencies=Dependências composer.dependencies.development=Dependências de desenvolvimento conan.details.repository=Repositório +conan.registry=Configure este registo usando a linha de comandos: conan.install=Para instalar o pacote usando o Conan, execute o seguinte comando: +conda.registry=Configure este registo como um repositório Conda no seu ficheiro .condarc: conda.install=Para instalar o pacote usando o Conda, execute o seguinte comando: container.details.type=Tipo de imagem container.details.platform=Plataforma @@ -3502,7 +3671,9 @@ container.layers=Camadas de imagem container.labels=Rótulos container.labels.key=Chave container.labels.value=Valor +cran.registry=Configure este registo no seu ficheiro Rprofile.site: cran.install=Para instalar o pacote, execute o seguinte comando: +debian.registry=Configure este registo usando a linha de comandos: debian.registry.info=Escolha $distribution e $component da lista abaixo. debian.install=Para instalar o pacote, execute o seguinte comando: debian.repository=Informação do repositório @@ -3511,11 +3682,16 @@ debian.repository.components=Componentes debian.repository.architectures=Arquitecturas generic.download=Descarregar pacote usando a linha de comandos: go.install=Instale o pacote a partir da linha de comandos: +helm.registry=Configure este registo usando a linha de comandos: helm.install=Para instalar o pacote, execute o seguinte comando: +maven.registry=Configure este registo no seu ficheiro pom.xml do projecto: +maven.install=Para usar este pacote, inclua no bloco dependencies do ficheiro pom.xml o seguinte: maven.install2=Executar usando a linha de comandos: maven.download=Para descarregar a dependência, execute na linha de comandos: +nuget.registry=Configure este registo usando a linha de comandos: nuget.install=Para instalar o pacote usando NuGet, execute o seguinte comando: nuget.dependency.framework=Estrutura alvo +npm.registry=Configure este registo no seu ficheiro .npmrc do projecto: npm.install=Para instalar o pacote usando o npm, execute o seguinte comando: npm.install2=ou adicione-o ao ficheiro package.json: npm.dependencies=Dependências @@ -3527,6 +3703,7 @@ npm.details.tag=Etiqueta pub.install=Para instalar o pacote usando o Dart, execute o seguinte comando: pypi.requires=Requer Python pypi.install=Para instalar o pacote usando o pip, execute o seguinte comando: +rpm.registry=Configure este registo usando a linha de comandos: rpm.distros.redhat=em distribuições baseadas no RedHat rpm.distros.suse=em distribuições baseadas no SUSE rpm.install=Para instalar o pacote, execute o seguinte comando: @@ -3539,6 +3716,7 @@ rubygems.dependencies.runtime=Dependências do tempo de execução (runtime) rubygems.dependencies.development=Dependências de desenvolvimento rubygems.required.ruby=Requer a versão do Ruby rubygems.required.rubygems=Requer a versão do RubyGem +swift.registry=Configure este registo usando a linha de comandos: swift.install=Adicione o pacote no seu ficheiro Package.swift: swift.install2=e execute o seguinte comando: vagrant.install=Para adicionar uma máquina virtual Vagrant, execute o seguinte comando: diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index ca7ae8a9626..c55ee0c6ac0 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -44,6 +44,7 @@ webauthn_use_twofa=Telefonunuzdan iki aşamalı doğrulama kodu kullanın webauthn_error=Güvenlik anahtarınız okunamıyor. webauthn_unsupported_browser=Tarayıcınız henüz WebAuthn desteklemiyor. webauthn_error_unknown=Bilinmeyen bir hata oluştu. Lütfen tekrar deneyin. +webauthn_error_insecure=WebAuthn sadece güvenli bağlantıyı destekler. HTTP üzerinden test etmek için "localhost" veya "127.0.0.1" adreslerini kullanabilirsiniz. webauthn_error_unable_to_process=Sunucu isteğinizi işleyemedi. webauthn_error_duplicated=Güvenlik anahtarının bu istek için izni yok. Anahtarın halihazırda kayıtlı olmadığından emin olun. webauthn_error_empty=Bu anahtar için bir isim belirlemelisiniz. @@ -116,8 +117,10 @@ files=Dosyalar error=Hata error404=Ulaşmaya çalıştığınız sayfa mevcut değil veya görüntüleme yetkiniz yok. +error503=Sunucu isteğinizi gerçekleştiremedi. Lütfen daha sonra tekrar deneyin. go_back=Geri Git invalid_data=Geçersiz veri: %v +nothing_has_been_changed=Hiçbir şey değişmedi. never=Asla unknown=Bilinmiyor @@ -129,6 +132,7 @@ unpin=Sabitlemeyi kaldır artifacts=Yapılar expired=Süresi doldu +confirm_delete_artifact=%s yapısını silmek istediğinizden emin misiniz? archived=Arşivlenmiş @@ -165,18 +169,33 @@ no_results_found=Sonuç bulunamadı. internal_error_skipped=Dahili bir hata oluştu ama atlandı: %s [search] +search=Ara... type_tooltip=Arama türü fuzzy=Bulanık +fuzzy_tooltip=Arama terimine benzeyen sonuçları da içer words=Kelimeler words_tooltip=Sadece arama terimi kelimeleriyle eşleşen sonuçları içer regexp=Regexp regexp_tooltip=Sadece regexp arama terimiyle tamamen eşleşen sonuçları içer exact=Tam exact_tooltip=Sadece arama terimiyle tamamen eşleşen sonuçları içer +repo_kind=Depoları ara... +user_kind=Kullanıcıları ara... +org_kind=Organizasyonları ara... +team_kind=Takımları ara... +code_kind=Kod ara... code_search_unavailable=Kod arama şu an mevcut değil. Lütfen site yöneticisiyle iletişime geçin. code_search_by_git_grep=Mevcut kod arama sonuçları "git grep" ile sağlanıyor. Eğer yönetici Depo Dizinleyici'yi etkinleştirirse daha iyi sonuçlar çıkabilir. +package_kind=Paketleri ara... +project_kind=Projeleri ara... +branch_kind=Dalları ara... +tag_kind=Etiketleri ara... tag_tooltip=Eşleşen etiketler için arama. Herhangi bir numara serisi bulmak için '%' kullanın. +commit_kind=İşlemeleri ara... +runner_kind=Çalıştırıcıları ara... no_results=Eşleşen sonuç bulunamadı. +issue_kind=Konuları ara... +pull_kind=Değişiklikleri ara... keyword_search_unavailable=Anahtar kelime ile arama şu an mevcut değil. Lütfen site yöneticinizle iletişime geçin. [aria] @@ -212,6 +231,8 @@ buttons.enable_monospace_font=Eşaralıklı yazıtipini etkinleştir buttons.disable_monospace_font=Eşaralıklı yazıtipini devre dışı bırak [filter] +string.asc=A - Z +string.desc=Z - A [error] occurred=Bir hata oluştu @@ -232,6 +253,7 @@ license_desc=Gidin ve belgeleri okuyun. require_db_desc=Gitea MySQL, PostgreSQL, MSSQL, SQLite3 veya TiDB (MySQL protokolü) gerektirir. @@ -252,6 +274,7 @@ reinstall_confirm_check_3=Bu Gitea'nın doğru app.ini konumuyla çalıştığı err_empty_db_path=SQLite3 veritabanı dosya yolu boş olamaz. no_admin_and_disable_registration=Bir yönetici hesabı oluşturmadan kullanıcı kaydını kapatamazsınız. err_empty_admin_password=Yönetici parolası boş olamaz. +err_empty_admin_email=Yönetici e-postası boş olamaz. general_title=Genel Ayarlar app_name=Site Başlığı diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 01e35820a1a..f834d92b264 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -44,6 +44,7 @@ webauthn_use_twofa=使用来自手机中的两步验证码 webauthn_error=无法读取安全密钥。 webauthn_unsupported_browser=您的浏览器目前不支持 WebAuthn。 webauthn_error_unknown=发生未知错误。请重试。 +webauthn_error_insecure=WebAuthn 仅支持安全连接。如果要在 HTTP 协议上进行测试,请使用 "localhost" 或 "127.0.0.1" 作为访问来源 webauthn_error_unable_to_process=服务器无法处理您的请求。 webauthn_error_duplicated=此安全密钥未被许可用于这个请求。请确保该密钥尚未注册。 webauthn_error_empty=您必须为此密钥设置一个名称。 @@ -111,11 +112,12 @@ copy_type_unsupported=无法复制此类型的文件内容 write=撰写 preview=预览 -loading=正在加载... +loading=正在加载… files=文件 error=错误 error404=您正尝试访问的页面 不存在 或 您尚未被授权 查看该页面。 +error503=服务器无法完成您的请求,请稍后重试。 go_back=返回 invalid_data=无效数据: %v @@ -124,7 +126,7 @@ unknown=未知 rss_feed=RSS 订阅源 -pin=固定 +pin=置顶 unpin=取消置顶 artifacts=产物 @@ -166,18 +168,33 @@ no_results_found=未找到结果 internal_error_skipped=发生内部错误,但已跳过: %s [search] +search=搜索… type_tooltip=搜索类型 fuzzy=模糊 +fuzzy_tooltip=包含近似匹配搜索词的结果 words=词 words_tooltip=仅包含匹配搜索词的结果 regexp=正则表达式 regexp_tooltip=仅包含匹配正则表达式搜索词的结果 exact=精确 exact_tooltip=仅包含精确匹配搜索词的结果 +repo_kind=搜索仓库… +user_kind=搜索用户… +org_kind=搜索组织… +team_kind=搜索团队… +code_kind=搜索代码… code_search_unavailable=代码搜索当前不可用。请与网站管理员联系。 code_search_by_git_grep=当前代码搜索结果由「git grep」提供。如果站点管理员启用仓库索引器,可能会有更好的结果。 -tag_tooltip=搜索匹配的标签。使用「%」来匹配任何序列的数字。 +package_kind=搜索软件包… +project_kind=搜索项目… +branch_kind=搜索分支… +tag_kind=搜索 Git 标签… +tag_tooltip=搜索匹配的 Git 标签。使用「%」来匹配任何序列的数字。 +commit_kind=搜索提交记录… +runner_kind=搜索运行器… no_results=未找到匹配结果 +issue_kind=搜索工单… +pull_kind=搜索合并请求… keyword_search_unavailable=按关键字搜索当前不可用。请联系站点管理员。 [aria] @@ -213,6 +230,8 @@ buttons.enable_monospace_font=启用等宽字体 buttons.disable_monospace_font=禁用等宽字体 [filter] +string.asc=A - Z +string.desc=Z - A [error] occurred=发生了一个错误 @@ -233,6 +252,7 @@ license_desc=所有的代码都开源在 官方文档 后再对本页面进行填写。 require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库 @@ -249,10 +269,16 @@ path=数据库文件路径 sqlite_helper=SQLite3 数据库的文件路径。
如果以服务的方式运行 Gitea,请输入绝对路径。 reinstall_error=您正在尝试安装到一个已经有 Gitea 数据的数据库中 reinstall_confirm_message=使用现有的 Gitea 数据库重新安装可能会导致多个问题。在大多数情况下,您应该使用您现有的「app.ini」来运行 Gitea。如果您知道自己在做什么,请确认以下内容: +reinstall_confirm_check_1=使用 app.ini 中 SECRET KEY 加密的数据可能会丢失:用户可能无法使用 2FA/OTP 登录,仓库镜像可能无法正常工作。勾选此框,表示您确认当前 app.ini 文件包含正确的 SECRET KEY。 +reinstall_confirm_check_2=代码仓库和设置可能需要重新同步。勾选此框,表示您确认将手动重新同步仓库和 SSH authorized_keys 的钩子。您确认您将确保代码仓库和镜像设置是正确的。 reinstall_confirm_check_3=您确认您绝对肯定这个 Gitea 在正确的 app.ini 位置上运行,而且您确定您必须重新安装。您确认您知晓上述风险。 err_empty_db_path=SQLite 数据库文件路径不能为空。 no_admin_and_disable_registration=您不能够在未创建管理员用户的情况下禁止注册。 err_empty_admin_password=管理员密码不能为空。 +err_empty_admin_email=管理员邮箱不能为空。 +err_admin_name_is_reserved=管理员用户名无效,用户名是保留的 +err_admin_name_pattern_not_allowed=管理员用户名无效,用户名是保留字 +err_admin_name_is_invalid=管理员用户名无效 general_title=一般设置 app_name=站点名称 @@ -268,6 +294,7 @@ domain_helper=服务器的域名或主机地址。 ssh_port=SSH 服务端口 ssh_port_helper=SSH 服务器的端口号,为空则禁用它。 http_port=HTTP 服务端口 +http_port_helper=Gitea Web 服务器将侦听的端口号。 app_url=基础URL app_url_helper=用于 HTTP (S) 克隆和邮件通知的基本地址。 log_root_path=日志路径 @@ -288,9 +315,9 @@ server_service_title=服务器和第三方服务设置 offline_mode=启用本地模式 offline_mode_popup=禁用第三方 CDN 并在本地服务所有资源。 disable_gravatar=禁用 Gravatar 头像 -disable_gravatar_popup=禁用 Gravatar 和第三方头像源。除非用户在本地上传头像, 否则将使用默认的头像。 +disable_gravatar_popup=禁用 Gravatar 和第三方头像源。除非用户在本地上传头像,否则将使用默认头像。 federated_avatar_lookup=启用 Federated 头像 -federated_avatar_lookup_popup=启用 Federated Avatars 查找以使用开源的 Libravatar 服务。 +federated_avatar_lookup_popup=启用 Federated 头像查找以使用开源的 Libravatar 服务。 disable_registration=禁止用户自助注册 disable_registration_popup=禁用用户自助注册。只有管理员才能创建新的用户帐户。 allow_only_external_registration_popup=仅允许通过外部服务注册 @@ -316,21 +343,22 @@ invalid_db_table=数据库表「%s」无效:%v invalid_repo_path=仓库根目录设置无效:%v invalid_app_data_path=应用数据路径无效: %v run_user_not_match=运行用户名不是当前的用户名:%s -> %s -internal_token_failed=生成内部令牌失败: %v -secret_key_failed=生成密钥失败: %v +internal_token_failed=生成内部令牌失败:%v +secret_key_failed=生成密钥失败:%v save_config_failed=应用配置保存失败:%v invalid_admin_setting=管理员帐户设置无效: %v invalid_log_root_path=日志路径无效: %v default_keep_email_private=默认情况下隐藏邮箱地址 default_keep_email_private_popup=默认情况下,隐藏新用户帐户的邮箱地址。 default_allow_create_organization=默认情况下允许创建组织 -default_allow_create_organization_popup=默认情况下, 允许新用户帐户创建组织。 +default_allow_create_organization_popup=默认情况下,允许新用户帐户创建组织。 default_enable_timetracking=默认情况下启用时间跟踪 default_enable_timetracking_popup=默认情况下启用新仓库的时间跟踪。 no_reply_address=隐藏邮件域 no_reply_address_helper=具有隐藏邮箱地址的用户的域名。例如,如果隐藏邮箱域名设置为「noreply.example.org」,那么用户名「joe」在 Git 中将显示为「joe@noreply.example.org」。 password_algorithm=密码哈希算法 invalid_password_algorithm=无效的密码哈希算法 +password_algorithm_helper=设置密码散列算法。算法有不同的要求和强度。 argon2 算法相当安全,但使用大量内存,因此可能不适合小型系统。 enable_update_checker=启用更新检查 enable_update_checker_helper=通过连接到 gitea.io 定期检查新版本发布。 env_config_keys=环境配置 @@ -402,6 +430,8 @@ allow_password_change=要求用户更改密码(推荐) reset_password_mail_sent_prompt=确认邮件已被发送到 %s。请您在 %s 内检查您的收件箱 ,完成密码重置流程。 active_your_account=激活您的帐户 account_activated=帐户已激活 +prohibit_login=禁止登录 +prohibit_login_desc=您的帐户被禁止登录,请与网站管理员联系。 resent_limit_prompt=您请求发送激活邮件过于频繁,请等待 3 分钟后再试! has_unconfirmed_mail=%s 您好,系统检测到您有一封发送至 %s 但未被确认的邮件。如果您未收到激活邮件,或需要重新发送,请单击下方的按钮。 change_unconfirmed_mail_address=如果您的注册邮箱地址不正确,您可以在此更改并重新发送新的确认邮件。 @@ -422,6 +452,7 @@ use_scratch_code=使用验证口令 twofa_scratch_used=您已经使用了您的验证口令。您将会转到两步验证设置页面以便移除您的注册设备或者重新生成新的验证口令。 twofa_passcode_incorrect=您的验证码不正确。如果您丢失了您的设备,请使用您的验证口令。 twofa_scratch_token_incorrect=您的验证口令不正确。 +twofa_required=您必须设置两步验证来访问仓库,或者尝试重新登录。 login_userpass=登录 login_openid=OpenID oauth_signup_tab=注册帐号 @@ -440,13 +471,17 @@ openid_connect_desc=所选的 OpenID URI 未知。在这里关联一个新帐户 openid_register_title=创建新帐户 openid_register_desc=所选的 OpenID URI 未知。在这里关联一个新帐户。 openid_signin_desc=输入您的OpenID地址。例如:alice.openid.example.org 或 https://openid.example.org/alice. +disable_forgot_password_mail=由于未设置邮箱,帐户恢复被禁用。 请联系您的站点管理员。 +disable_forgot_password_mail_admin=帐户恢复仅在设置邮箱后可用。 请设置邮箱以启用帐户恢复。 email_domain_blacklisted=您不能使用您的邮箱地址注册。 authorize_application=应用授权 authorize_redirect_notice=如果您授权此应用,您将会被重定向到 %s。 authorize_application_created_by=此应用由 %s 创建。 +authorize_application_description=如果您允许,它将能够读取和修改您的所有帐户信息,包括私人仓库和组织。 authorize_application_with_scopes=范围:%s authorize_title=授权 %s 访问您的帐户? authorization_failed=授权失败 +authorization_failed_desc=因为检测到无效请求,授权失败。请尝试联系您授权应用的管理员。 sspi_auth_failed=SSPI 认证失败 password_pwned=此密码出现在 被盗密码 列表上并且曾经被公开。 请使用另一个密码再试一次。 password_pwned_err=无法完成对 HaveIBeenPwned 的请求 @@ -472,6 +507,7 @@ activate_email.text=请在 %s 时间内,点击以下链接,以验证 register_notify=欢迎来到 %s register_notify.title=%[1]s,欢迎来到 %[2]s register_notify.text_1=这是您的 %s 注册确认邮件 ! +register_notify.text_2=您现在可以以用户名 %s 登录。 register_notify.text_3=如果此账户已为您创建,请先 设置您的密码。 reset_password=恢复您的账户 @@ -509,8 +545,9 @@ release.download.targz=源代码(TAR.GZ) repo.transfer.subject_to=%s 想要将「%s」转移给 %s repo.transfer.subject_to_you=%s 想要将「%s」转移给您 repo.transfer.to_you=您 +repo.transfer.body=访问 %s 以接受或拒绝转移,亦可忽略此邮件。 -repo.collaborator.added.subject=%s 把您添加到了 %s +repo.collaborator.added.subject=%s 把您添加到 %s repo.collaborator.added.text=您已被添加为仓库的协作者: team_invite.subject=%[1]s 邀请您加入组织 %[2]s @@ -549,8 +586,8 @@ SSPISeparatorReplacement=分隔符 SSPIDefaultLanguage=默认语言 require_error=不能为空。 -alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 -alpha_dash_dot_error=` 应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。` +alpha_dash_error=`应该只包含字母数字、破折号('-')和下划线('_')。` +alpha_dash_dot_error=`应该只包含字母数字、破折号('-')、下划线('_')和点('.')。` git_ref_name_error=` 必须是格式良好的 git 引用名称。` size_error=长度必须为 %s。 min_size_error=长度最小为 %s 个字符。 @@ -560,6 +597,7 @@ url_error=`「%s」不是一个有效的 URL。` include_error=`必须包含子字符串「%s」。` glob_pattern_error=`匹配表达式无效:%s.` regex_pattern_error=`正则表达式无效:%s.` +username_error=`只能包含字母数字('0-9'、'a-z'、'A-Z')破折号('-')下划线('_')和点('.')。不能以非字母数字字符开头和结尾且不允许连续的非字母数字字符。` invalid_group_team_map_error=`映射无效: %s` unknown_error=未知错误: captcha_incorrect=验证码不正确。 @@ -574,14 +612,17 @@ username_has_not_been_changed=用户名未更改 repo_name_been_taken=仓库名称已使用。 repository_force_private=「强制私有」已启用:私有仓库不能被公开。 repository_files_already_exist=此仓库已存在文件。请联系系统管理员。 +repository_files_already_exist.adopt=此仓库已存在文件,只能被收录。 repository_files_already_exist.delete=此仓库已存在文件,必须先删除他们。 repository_files_already_exist.adopt_or_delete=此仓库已存在文件,要么删除他们,要么收录他们。 visit_rate_limit=远程访问达到速度限制。 +2fa_auth_required=远程访问需要两步验证。 org_name_been_taken=组织名称已使用。 team_name_been_taken=团队名称已使用。 team_no_units_error=至少选择一项仓库单元。 email_been_used=该邮箱地址已在使用中。 email_invalid=此邮箱地址无效。 +email_domain_is_not_allowed=用户 %s 与EMAIL_DOMAIN_ALLOWLIT 或 EMAIL_DOMAIN_BLOCKLIT 冲突。请确保您的操作是预期的。 openid_been_used=OpenID 地址「%s」已被使用。 username_password_incorrect=用户名或密码不正确。 password_complexity=密码未达到复杂程度要求: @@ -606,8 +647,14 @@ invalid_ssh_key=无法验证您的 SSH 密钥:%s invalid_gpg_key=无法验证您的 GPG 密钥:%s invalid_ssh_principal=无效的规则:%s must_use_public_key=您提供的密钥是私钥。不要在任何地方上传您的私钥,请改用您的公钥。 +unable_verify_ssh_key=无法验证 SSH 密钥,请仔细检查是否有错误。 auth_failed=授权验证失败:%v +still_own_repo=此帐户仍拥有至少一个仓库,您需要先删除或转移它们。 +still_has_org=此帐户隶属于一个或多个组织,请先退出这些组织。 +still_own_packages=您的账户拥有一个或多个软件包,请先删除它们。 +org_still_own_repo=该组织仍然是某些仓库的拥有者,请先删除或转移它们! +org_still_own_packages=该组织仍然是一个或多个软件包的拥有者,请先删除它们。 target_branch_not_exist=目标分支不存在。 target_ref_not_exist=目标引用 %s 不存在 @@ -638,9 +685,11 @@ settings=用户设置 form.name_reserved=用户名「%s」被保留。 form.name_pattern_not_allowed=用户名中不允许使用「%s」格式。 +form.name_chars_not_allowed=用户名「%s」包含无效字符。 block.block=屏蔽 block.block.user=屏蔽用户 +block.block.org=屏蔽用户访问组织 block.block.failure=屏蔽用户失败:%s block.unblock=取消屏蔽 block.unblock.failure=取消屏蔽用户失败:%s @@ -653,6 +702,7 @@ block.info_3=通过 @ 提及您的用户名向您发送通知 block.info_4=邀请您作为协作者到他们的仓库中 block.info_5=在仓库中点赞、派生或关注 block.info_6=打开和评论工单或合并请求 +block.info_7=在问题或合并请求中对您的评论做出反应 block.user_to_block=要屏蔽的用户 block.note=备注 block.note.title=可选备注: @@ -703,8 +753,9 @@ cancel=取消操作 language=界面语言 ui=主题 hidden_comment_types=隐藏的评论类型 -hidden_comment_types.ref_tooltip=注释此问题在何处被提及过,如另一个问题、代码提交等 -hidden_comment_types.issue_ref_tooltip=注释用户在何处更改了与此问题相关联的分支/标签 +hidden_comment_types_description=此处选中的注释类型不会显示在工单页面上。比如,勾选「标签」删除所有「{user} 添加/删除的 {label}」注释。 +hidden_comment_types.ref_tooltip=注释此工单在何处被提及过,如另一个工单、提交… +hidden_comment_types.issue_ref_tooltip=注释用户在何处更改了与此工单相关联的分支 / Git 标签 comment_type_group_reference=引用 comment_type_group_label=标签 comment_type_group_milestone=里程碑 @@ -725,13 +776,13 @@ keep_activity_private=隐藏个人资料页面中的活动 keep_activity_private_popup=使活动仅对您和管理员可见 lookup_avatar_by_mail=从邮箱地址查找头像 -federated_avatar_lookup=Federated Avatar 查找 -enable_custom_avatar=启动自定义头像 +federated_avatar_lookup=查找 Federated 头像 +enable_custom_avatar=使用自定义头像 choose_new_avatar=选择新的头像 update_avatar=更新头像 delete_current_avatar=删除当前头像 uploaded_avatar_not_a_image=上传的文件不是一张图片。 -uploaded_avatar_is_too_big=上传的文件大小(%d KiB) 超过最大限制(%d KiB)。 +uploaded_avatar_is_too_big=上传的文件大小(%d KiB)超过最大限制(%d KiB)。 update_avatar_success=您的头像已更新。 update_user_avatar_success=用户头像已更新。 cropper_prompt=您可以在保存前编辑图像。编辑的图像将被保存为 PNG 格式。 @@ -750,15 +801,18 @@ manage_themes=选择默认主题 manage_openid=管理 OpenID 地址 email_desc=您的主邮箱地址将用于通知、密码恢复以及基于网页的 Git 操作(如果它未设为隐藏)。 theme_desc=这将是您在整个网站上的默认主题。 -primary=主要 +theme_colorblindness_help=颜色障碍主题支持 +theme_colorblindness_prompt=Gitea 仅有少数主题存在基本的颜色障碍支持,这些主题只定义了少数颜色。这项工作仍在进行中,可以通过在主题的 CSS 文件中定义更多颜色来实现更多改进。 +primary=主 activated=已激活 requires_activation=需要激活 primary_email=设为主邮箱 activate_email=发送激活邮件 activations_pending=等待激活 +can_not_add_email_activations_pending=有一个待处理的激活请求,请稍等几分钟后再尝试添加新的邮箱地址。 delete_email=移除 email_deletion=移除邮箱地址 -email_deletion_desc=邮箱地址和相关信息将会被删除。使用此邮箱地址发送的Git提交将会保留,继续? +email_deletion_desc=邮箱地址和相关信息将会被删除。使用此邮箱地址发送的 Git 提交将会保留,继续? email_deletion_success=您的邮箱地址已移除。 theme_update_success=您的主题已更新。 theme_update_error=所选主题不存在。 @@ -793,7 +847,7 @@ key_content_gpg_placeholder=以 '-----BEGIN PGP PUBLIC KEY BLOCK-----' 开头 add_new_principal=添加规则 ssh_key_been_used=此 SSH 密钥已添加到服务器。 ssh_key_name_used=使用相同名称的 SSH 公钥已经存在。 -ssh_principal_been_used=此规则已经加入到了服务器。 +ssh_principal_been_used=此规则已经加入到服务器。 gpg_key_id_used=使用相同名称的 GPG 公钥已经存在。 gpg_no_key_email_found=此 GPG 密钥与您帐户关联的任何已激活邮箱地址均不匹配。如果您已对提供的令牌进行签名,仍可添加该密钥。 gpg_key_matched_identities=匹配的身份: @@ -801,6 +855,7 @@ gpg_key_matched_identities_long=此密钥中包含的身份信息与以下此用 gpg_key_verified=已验证的密钥 gpg_key_verified_long=密钥已通过令牌验证,除与此密钥匹配的任何身份外,还可用于验证与该用户任何已激活邮箱地址匹配的提交。 gpg_key_verify=验证 +gpg_invalid_token_signature=提供的 GPG 密钥、签名和令牌不匹配或过期。 gpg_token_required=您必须为下面的令牌提供签名 gpg_token=令牌 gpg_token_help=您可以使用以下方式生成签名: @@ -810,6 +865,7 @@ verify_gpg_key_success=GPG 密钥「%s」已验证。 ssh_key_verified=已验证的密钥 ssh_key_verified_long=密钥已通过令牌验证,可用于验证与该用户任何已激活邮箱地址匹配的提交。 ssh_key_verify=验证 +ssh_invalid_token_signature=提供的 SSH 密钥、签名或令牌不匹配或令牌已过期。 ssh_token_required=您必须为下面的令牌提供签名 ssh_token=令牌 ssh_token_help=您可以使用以下方式生成签名: @@ -830,6 +886,7 @@ gpg_key_deletion=删除 GPG 密钥 ssh_principal_deletion=删除 SSH 证书规则 ssh_key_deletion_desc=删除 SSH 公钥将取消对应的私钥对您的 Gitea 帐户的访问权限。继续? gpg_key_deletion_desc=删除 GPG 公钥将无法认证对应私钥签名的提交,继续? +ssh_principal_deletion_desc=删除此 SSH 证书规则将取消它对您的账户的访问权限。继续? ssh_key_deletion_success=SSH 密钥已删除。 gpg_key_deletion_success=GPG 密钥已删除。 ssh_principal_deletion_success=此规则删除成功。 @@ -888,9 +945,10 @@ remove_oauth2_application_desc=删除 OAuth2 应用将撤销所有签名的访 remove_oauth2_application_success=该应用已删除。 create_oauth2_application=创建新的 OAuth2 应用程序 create_oauth2_application_button=创建应用 -create_oauth2_application_success=您已成功创建了一个新的 OAuth2 应用。 -update_oauth2_application_success=您已成功更新了此 OAuth2 应用。 +create_oauth2_application_success=您已成功创建一个新的 OAuth2 应用。 +update_oauth2_application_success=您已成功更新此 OAuth2 应用。 oauth2_application_name=应用名称 +oauth2_confidential_client=机密客户端。对于需要保密的应用(例如 Web 应用),请选择此选项。对于包括桌面和移动应用在内的本机应用,请勿选择此选项。 oauth2_skip_secondary_authorization=首次授权后允许公共客户端跳过授权步骤。 可能会带来安全风险。 oauth2_redirect_uris=重定向 URI。每行一个 URI。 save_application=保存 @@ -905,9 +963,11 @@ oauth2_application_remove_description=移除一个OAuth2应用将会阻止它访 oauth2_application_locked=如果配置启用,Gitea 将在启动时预注册一些 OAuth2 应用程序。 为了防止意外的行为, 这些应用既不能编辑也不能删除。请参阅 OAuth2 文档以获取更多信息。 authorized_oauth2_applications=已授权的 OAuth2 应用 +authorized_oauth2_applications_description=您已授予这些第三方应用程序访问您的个人 Gitea 账户的权限。请撤销那些您不再需要的应用程序的访问权限。 revoke_key=撤销 revoke_oauth2_grant=撤回权限 -revoke_oauth2_grant_success=成功撤销了访问权限。 +revoke_oauth2_grant_description=确定撤销此三方应用程序的授权,并阻止此应用程序访问您的数据? +revoke_oauth2_grant_success=成功撤销访问权限。 twofa_desc=为保护您的账号密码安全,您可以使用智能手机或其它设备来接收时间强相关的一次性密码(TOTP)。 twofa_recovery_tip=如果您丢失了您的设备,您将能够使用一次性恢复密钥来重新获得对您账户的访问。 @@ -916,21 +976,23 @@ twofa_not_enrolled=您的账号未开启两步验证。 twofa_disable=禁用两步认证 twofa_scratch_token_regenerate=重新生成初始令牌 twofa_scratch_token_regenerated=您的初始令牌现在是 %s。将其存放在安全的地方,它将不会再次显示。 -twofa_disable_note=如果需要, 可以禁用双因素身份验证。 +twofa_enroll=启用两步验证 +twofa_disable_note=如果需要,您可以禁用两步验证。 twofa_disable_desc=关掉两步验证会使得您的账号不安全,继续执行? -regenerate_scratch_token_desc=如果您丢失了您的恢复密钥或已经使用它登录, 您可以在这里重置它。 +regenerate_scratch_token_desc=如果您丢失了您的恢复密钥或已经使用它登录,您可以在这里重置它。 twofa_disabled=两步验证已禁用。 scan_this_image=使用您的授权应用扫描这张图片: or_enter_secret=或者输入密钥:%s then_enter_passcode=并输入应用程序中显示的密码: passcode_invalid=密码不正确。再试一次。 -twofa_enrolled=您的账号已经启用了两步验证。请保存初始令牌(%s)到一个安全的地方,此令牌仅显示一次。 +twofa_enrolled=您的账号已经启用两步验证。请保存初始令牌(%s)到一个安全的地方,此令牌仅显示一次。 twofa_failed_get_secret=获取 secret 失败。 webauthn_desc=安全密钥是包含加密密钥的硬件设备。它们可以用于双因素身份验证。安全密钥必须支持 WebAuthn 身份验证器 标准。 webauthn_register_key=添加安全密钥 webauthn_nickname=昵称 webauthn_delete_key=移除安全密钥 +webauthn_delete_key_desc=如果删除了安全密钥,则不能再使用它登录。继续? webauthn_key_loss_warning=如果您丢失了您的安全密钥,您将无法访问您的帐户。 webauthn_alternative_tip=您可能想要配置额外的身份验证方法。 @@ -949,7 +1011,7 @@ repos_none=您并不拥有任何仓库。 delete_account=删除当前帐户 delete_prompt=此操作将永久删除您的用户帐户。它 无法 被撤消。 -delete_with_all_comments=您的帐户年龄小于 %s。为了避免幽灵评论,所有工单/合并请求的评论都将与它一起被删除。 +delete_with_all_comments=您的帐户年龄小于 %s。为了避免幽灵评论,所有工单 / 合并请求的评论都将与它一起被删除。 confirm_delete_account=确认删除帐户 delete_account_title=删除当前帐户 delete_account_desc=确实要永久删除此用户帐户吗? @@ -959,7 +1021,7 @@ email_notifications.onmention=仅被提及时通知 email_notifications.disable=停用邮件通知 email_notifications.submit=设置邮件通知 email_notifications.andyourown=仅与您相关的通知 -email_notifications.actions.desc=设置了 Gitea 工作流 的仓库中工作流运行的通知。 +email_notifications.actions.desc=已设置 Gitea 工作流 的仓库中工作流运行的通知。 email_notifications.actions.failure_only=仅在工作流运行失败时通知 visibility=用户可见性 @@ -997,7 +1059,8 @@ fork_visibility_helper=无法更改派生仓库的可见性。 fork_branch=要克隆为派生的分支 all_branches=所有分支 view_all_branches=查看所有分支 -view_all_tags=查看所有标签 +view_all_tags=查看所有 Git 标签 +fork_no_valid_owners=这个代码仓库无法被派生,因为没有有效的所有者。 fork.blocked_user=无法克隆仓库,因为您被仓库所有者屏蔽。 use_template=使用此模板 open_with_editor=用 %s 打开 @@ -1036,16 +1099,18 @@ default_branch_label=默认 default_branch_helper=默认分支是用于合并请求和代码提交的基础分支。 mirror_prune=修剪 mirror_prune_desc=删除过时的远程跟踪引用 -mirror_interval=镜像间隔 (有效的时间单位是 'h', 'm', 's')。0 禁用自动定期同步 (最短间隔: %s) +mirror_interval=镜像间隔(有效的时间单位是 'h'、'm'、's')。0 禁用自动定期同步(最短间隔: %s) mirror_interval_invalid=镜像间隔无效。 mirror_sync=已同步 mirror_sync_on_commit=推送提交时同步 mirror_address=从 URL 克隆 mirror_address_desc=在授权框中输入必要的凭据。 +mirror_address_url_invalid=提供的 URL 无效。请确保 URL 的所有组成部分均已正确转义。 mirror_address_protocol_invalid=提供的URL无效。只能使用http(s)://或git://地址进行镜像操作。 mirror_lfs=大文件存储 (LFS) mirror_lfs_desc=镜像 LFS 数据。 mirror_lfs_endpoint=LFS 网址 +mirror_lfs_endpoint_desc=同步将尝试使用克隆 URL 来 确定 LFS 服务器。如果仓库 LFS 数据存储在其他位置,您还可以指定自定义网址。 mirror_last_synced=上次同步 mirror_password_placeholder=(未更改) mirror_password_blank_placeholder=(未设置) @@ -1058,6 +1123,7 @@ stars=点赞数 reactions_more=再加载 %d unit_disabled=站点管理员已禁用此仓库单元。 language_other=其它 +adopt_search=输入用户名以搜索未被收录的仓库…(留空以查找全部) adopt_preexisting_label=收录仓库 adopt_preexisting=收录已存在的仓库 adopt_preexisting_content=从 %s 创建仓库 @@ -1099,6 +1165,8 @@ template.issue_labels=工单标签 template.one_item=必须至少选择一个模板项 template.invalid=必须选择一个模板仓库 +archive.title=该仓库已被归档。您可以查看文件和克隆它,但不能创建工单、合并请求或推送提交。 +archive.title_date=该仓库已于 %s 归档。您可以查看文件和克隆它,但不能创建工单、合并请求或推送提交。 archive.issue.nocomment=此仓库已存档,您不能在此工单添加评论。 archive.pull.nocomment=此仓库已存档,您不能在此合并请求添加评论。 @@ -1115,6 +1183,7 @@ migrate_options_lfs=迁移 LFS 文件 migrate_options_lfs_endpoint.label=LFS 网址 migrate_options_lfs_endpoint.description=迁移将尝试使用您的 Git remote 来 确定 LFS 服务器。如果仓库 LFS 数据存储在其他位置,您还可以指定自定义网址。 migrate_options_lfs_endpoint.description.local=支持本地服务器路径。 +migrate_options_lfs_endpoint.placeholder=如果留空,网址将从克隆 URL 中得到 migrate_items=迁移项目 migrate_items_wiki=百科 migrate_items_milestones=里程碑 @@ -1126,8 +1195,10 @@ migrate_items_releases=发布 migrate_repo=迁移仓库 migrate.clone_address=从 URL 迁移/克隆 migrate.clone_address_desc=现有仓库的 HTTP(s) 或 Git "clone" URL +migrate.github_token_desc=您可以在此处输入一个或多个令牌(以逗号分隔),以绕过 GitHub API 速率限制来加快迁移速度。警告:滥用此功能可能会违反服务提供商的政策并导致帐户被封禁。 migrate.clone_local_path=或服务器本地路径 migrate.permission_denied=您没有获得导入本地仓库的权限。 +migrate.permission_denied_blocked=您不能从不允许的主机导入,请询问管理员以检查 ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS 设置。 migrate.invalid_local_path=本地路径无效。它不存在或不是一个目录。 migrate.invalid_lfs_endpoint=LFS 网址无效。 migrate.failed=迁移失败:%v @@ -1135,6 +1206,7 @@ migrate.migrate_items_options=需要访问令牌来迁移额外的内容 migrated_from=从 %[2]s 迁移 migrated_from_fake=从 %[1]s 迁移成功 migrate.migrate=从 %s 迁移 +migrate.migrating=正在从 %s 迁移… migrate.migrating_failed=从 %s 迁移失败。 migrate.migrating_failed.error=迁移失败:%s migrate.migrating_failed_no_addr=迁移失败。 @@ -1183,23 +1255,26 @@ clone_this_repo=克隆当前仓库 cite_this_repo=引用此仓库 create_new_repo_command=从命令行创建一个新的仓库 push_exist_repo=从命令行推送已经创建的仓库 +empty_message=这个家伙很懒,什么都没有推送。 broken_message=无法读取此仓库下的 Git 数据。 联系此实例的管理员或删除此仓库。 +no_branch=该仓库没有任何分支。 code=代码 code.desc=查看源码、文件、提交和分支。 branch=分支 tree=目录树 clear_ref=`清除当前引用` -filter_branch_and_tag=过滤分支或标签 -find_tag=查找标签 +filter_branch_and_tag=过滤分支或 Git 标签 +find_tag=查找 Git 标签 branches=分支列表 -tags=标签列表 +tags=Git 标签列表 issues=工单 pulls=合并请求 projects=项目 packages=软件包 actions=工作流 labels=标签 +org_labels_desc=组织级别的标签,可以被本组织下的 所有仓库 使用 org_labels_desc_manage=管理 milestone=里程碑 @@ -1208,8 +1283,8 @@ commits=提交 commit=提交 release=发布 releases=发布 -tag=标签 -released_this=发布 +tag=Git 标签 +released_this=发布于 tagged_this=已标记 file.title=%s 位于 %s file_raw=原始文件 @@ -1247,7 +1322,8 @@ commit_graph.monochrome=黑白 commit_graph.color=彩色 commit.contained_in=这个提交包含在: commit.contained_in_default_branch=此提交是默认分支的一部分 -commit.load_referencing_branches_and_tags=加载引用该提交的分支和标签 +commit.load_referencing_branches_and_tags=加载引用该提交的分支和 Git 标签 +commit.merged_in_pr=此提交已合并在合并请求 %s 中。 blame=Blame download_file=下载文件 normal_view=普通视图 @@ -1271,7 +1347,7 @@ editor.fork_before_edit=您必须派生这个仓库才能对此文件进行修 editor.delete_this_file=删除文件 editor.must_have_write_access=您必须具有写权限才能对此文件进行修改操作。 editor.file_delete_success=文件「%s」已删除。 -editor.name_your_file=命名文件... +editor.name_your_file=命名文件… editor.filename_help=通过键入名称后跟斜线 ("/") 来添加目录。通过在输入框的开头键入「退格」来删除目录。 editor.or=或 editor.cancel_lower=取消 @@ -1285,24 +1361,28 @@ editor.patch=应用补丁 editor.patching=打补丁: editor.fail_to_apply_patch=无法应用补丁 editor.new_patch=新补丁 -editor.commit_message_desc=添加一个可选的扩展描述... +editor.commit_message_desc=添加一个可选的扩展描述… editor.signoff_desc=在提交日志消息末尾添加签署人信息。 editor.commit_directly_to_this_branch=直接提交至 %s 分支。 editor.create_new_branch=为此提交创建一个 新的分支 并发起合并请求。 editor.create_new_branch_np=为此提交创建 新分支。 editor.propose_file_change=建议文件更改 editor.new_branch_name=为这次提交的新分支命名 -editor.new_branch_name_desc=新的分支名称... +editor.new_branch_name_desc=新的分支名称… editor.cancel=取消 editor.filename_cannot_be_empty=文件名不能为空。 editor.filename_is_invalid=文件名无效:「%s」。 +editor.commit_email=提交邮箱地址 +editor.invalid_commit_email=提交的邮箱地址无效。 editor.branch_does_not_exist=此仓库中不存在名为「%s」的分支。 editor.branch_already_exists=此仓库已存在名为「%s」的分支。 editor.directory_is_a_file=目录名「%s」已作为文件名在此仓库中存在。 +editor.file_is_a_symlink=`「%s」是一个符号链接,无法在 Web 编辑器中编辑` editor.filename_is_a_directory=文件名「%s」已作为目录名在此仓库中存在。 editor.file_modifying_no_longer_exists=正在修改的文件「%s」已不存在于此仓库。 editor.file_changed_while_editing=文件内容在您进行编辑时已经发生变动。单击此处 查看变动的具体内容,或者 再次提交 覆盖已发生的变动。 editor.file_already_exists=此仓库已经存在名为「%s」的文件。 +editor.commit_id_not_matching=提交 ID 与您开始编辑时的 ID 不匹配。请提交到补丁分支然后合并。 editor.push_out_of_date=推送似乎已经过时。 editor.commit_empty_file_header=提交一个空文件 editor.commit_empty_file_text=您要提交的文件是空的,继续吗? @@ -1310,7 +1390,7 @@ editor.no_changes_to_show=没有可以显示的变更。 editor.push_rejected_no_message=此修改被服务器拒绝并且没有反馈消息。请检查 Git 钩子。 editor.push_rejected=此修改被服务器拒绝。请检查 Git 钩子。 editor.push_rejected_summary=详细拒绝信息: -editor.add_subdir=添加目录 +editor.add_subdir=添加目录… editor.unable_to_upload_files=上传文件至「%s」失败:%v editor.upload_file_is_locked=文件「%s」被 %s 锁定。 editor.upload_files_to_dir=上传文件至「%s」 @@ -1328,12 +1408,13 @@ editor.fork_create_description=您不能直接编辑此仓库。您可以派生 editor.fork_edit_description=您不能直接编辑此仓库。 更改将写入您的派生仓库 %s,以便您可以创建一个合并请求。 editor.fork_not_editable=您已经派生了此仓库,但您的派生是不可编辑的。 editor.fork_failed_to_push_branch=推送分支 %s 到仓库失败。 +editor.fork_branch_exists=分支「%s」已存在于您的派生仓库中,请选择一个新的分支名称。 commits.desc=浏览代码修改历史 commits.commits=次代码提交 commits.no_commits=没有共同的提交。「%s」和「%s」的历史完全不同。 commits.nothing_to_compare=这些分支是相同的。 -commits.search.tooltip=`您可以在关键词前加上前缀,如"author:", "committer:", "after:", 或"before:", 例如 "retrin author:Alice before:2019-01-13"` +commits.search.tooltip=您可以在关键词前加上前缀,如「author:」、「committer:」、「after:」或「before:」,例如「retrin author:Alice before:2019-01-13」。 commits.search_branch=此分支 commits.search_all=所有分支 commits.author=作者 @@ -1407,7 +1488,7 @@ issues.filter_assignees=筛选指派人 issues.filter_milestones=筛选里程碑 issues.filter_projects=筛选项目 issues.filter_labels=筛选标签 -issues.filter_reviewers=筛选审核者 +issues.filter_reviewers=筛选评审人 issues.filter_no_results=没有结果 issues.filter_no_results_placeholder=请尝试调整您的搜索过滤器。 issues.new=创建工单 @@ -1427,8 +1508,9 @@ issues.new.clear_milestone=取消选中里程碑 issues.new.assignees=指派成员 issues.new.clear_assignees=取消指派成员 issues.new.no_assignees=未指派成员 -issues.new.no_reviewers=无审核者 +issues.new.no_reviewers=无评审人 issues.new.blocked_user=无法创建工单,因为您已被仓库所有者屏蔽。 +issues.edit.already_changed=无法保存对工单的更改。其内容似乎已被其他用户更改。请刷新页面并重新编辑以避免覆盖他们的更改。 issues.edit.blocked_user=无法编辑内容,因为您已被仓库所有者或工单创建者屏蔽。 issues.choose.get_started=开始 issues.choose.open_external_link=开启 @@ -1437,7 +1519,7 @@ issues.choose.blank_about=从默认模板创建一个工单。 issues.choose.ignore_invalid_templates=已忽略无效模板 issues.choose.invalid_templates=发现了 %v 个无效模板 issues.choose.invalid_config=问题配置包含错误: -issues.no_ref=分支/Git标签未指定 +issues.no_ref=分支 / Git 标签未指定 issues.create=创建工单 issues.new_label=创建标签 issues.new_label_placeholder=标签名称 @@ -1448,29 +1530,29 @@ issues.label_templates.info=还没有任何标签。您可以使用「创建标 issues.label_templates.helper=选择标签模板 issues.label_templates.use=使用标签集 issues.label_templates.fail_to_load_file=加载标签模板文件「%s」时发生错误:%v -issues.add_label=于 %[2]s 添加了标签 %[1]s -issues.add_labels=于 %[2]s 添加了标签 %[1]s -issues.remove_label=于 %[2]s 删除了标签 %[1]s -issues.remove_labels=于 %[2]s 删除了标签 %[1]s -issues.add_remove_labels=于 %[3]s 添加了标签 %[1]s ,删除了标签 %[2]s -issues.add_milestone_at=`于 %[2]s 添加了里程碑 %[1]s` -issues.add_project_at=`于 %[2]s 将此添加到 %[1]s 项目` -issues.move_to_column_of_project=`将此对象移至 %s 的 %s 中在 %s 上` -issues.change_milestone_at=`%[3]s 修改了里程碑从 %[1]s 到 %[2]s` -issues.change_project_at=于 %[3]s 将此从项目 %[1]s 移到 %[2]s -issues.remove_milestone_at=`%[2]s 删除了里程碑 %[1]s` -issues.remove_project_at=`于 %[2]s 将此工单从项目 %[1]s 中删除` +issues.add_label=于 %[2]s 添加标签 %[1]s +issues.add_labels=于 %[2]s 添加标签 %[1]s +issues.remove_label=于 %[2]s 移除标签 %[1]s +issues.remove_labels=于 %[2]s 移除标签 %[1]s +issues.add_remove_labels=于 %[3]s 添加标签 %[1]s 移除标签 %[2]s +issues.add_milestone_at=`于 %[2]s 添加里程碑 %[1]s` +issues.add_project_at=`于 %[2]s 将此工单添加到 %[1]s 项目` +issues.move_to_column_of_project=`将 %[3]s 上的 %[2]s 移至 %[1]s` +issues.change_milestone_at=`于 %[3]s 修改里程碑从 %[1]s 到 %[2]s` +issues.change_project_at=于 %[3]s 将项目从 %[1]s 移至 %[2]s +issues.remove_milestone_at=`于 %[2]s 删除里程碑 %[1]s` +issues.remove_project_at=`于 %[2]s 将此工单从项目 %[1]s 中移除` issues.deleted_milestone=(已删除) issues.deleted_project=`(已删除)` issues.self_assign_at=`于 %s 指派给自己` issues.add_assignee_at=`于 %[2]s 由 %[1]s 指派` -issues.remove_assignee_at=`%s 取消了指派在 %s` -issues.remove_self_assignment=`于 %s 取消了指派` +issues.remove_assignee_at=`于 %[2]s 由 %[1]s 取消指派` +issues.remove_self_assignment=`于 %s 取消指派` issues.change_title_at=`于 %[3]s 修改标题 %[1]s 为 %[2]s` -issues.change_ref_at=`将引用从 %s 更改为了 %s %s` -issues.remove_ref_at=`删除了引用 %s %s` -issues.add_ref_at=`添加了引用 %s %s` -issues.delete_branch_at=`于 %[2]s 删除了分支 %[1]s` +issues.change_ref_at=`于 %[3]s 修改引用 %[1]s 为 %[2]s` +issues.remove_ref_at=`于 %[2]s 删除引用 %[1]s` +issues.add_ref_at=`于 %[2]s 添加引用 %[1]s` +issues.delete_branch_at=`于 %[2]s 删除分支 %[1]s` issues.filter_label=标签筛选 issues.filter_label_exclude=`使用 alt + 鼠标左键 / 回车 排除标签` issues.filter_label_no_select=所有标签 @@ -1496,10 +1578,11 @@ issues.filter_type.assigned_to_you=指派给您的 issues.filter_type.created_by_you=由您创建的 issues.filter_type.mentioning_you=提及您的 issues.filter_type.review_requested=已请求评审 -issues.filter_type.reviewed_by_you=您评审过的 +issues.filter_type.reviewed_by_you=您已评审的 issues.filter_sort=排序 issues.filter_sort.latest=最新创建 issues.filter_sort.oldest=最早创建 +issues.filter_sort.recentupdate=最近更新 issues.filter_sort.leastupdate=最早更新 issues.filter_sort.mostcomment=最多评论 issues.filter_sort.leastcomment=最少评论 @@ -1540,33 +1623,33 @@ issues.context.edit=编辑 issues.context.delete=刪除 issues.no_content=没有提供说明。 issues.close=关闭工单 -issues.comment_pull_merged_at=已合并提交 %[1]s 到 %[2]s %[3]s -issues.comment_manually_pull_merged_at=手动合并提交 %[1]s 到 %[2]s %[3]s +issues.comment_pull_merged_at=于 %[3]s 合并提交 %[1]s 到 %[2]s +issues.comment_manually_pull_merged_at=于 %[3]s 手动合并提交 %[1]s 到 %[2]s issues.close_comment_issue=评论并关闭 issues.reopen_issue=重新打开 issues.reopen_comment_issue=评论并重新打开 issues.create_comment=评论 issues.comment.blocked_user=无法创建或编辑评论,因为您已被仓库所有者或工单创建者屏蔽。 issues.closed_at=`于 %[2]s 关闭此工单` -issues.reopened_at=`重新打开此问题 %[2]s` -issues.commit_ref_at=`于 %[2]s 在代码提交中引用了该工单` -issues.ref_issue_from=`于 %[2]s 引用了工单 %[4]s ` -issues.ref_pull_from=`于 %[2]s 引用了合并请求 %[4]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.reopened_at=`于 %[2]s 重新打开此工单` +issues.commit_ref_at=`于 %[2]s 在代码提交中引用该工单` +issues.ref_issue_from=`于 %[2]s 引用工单 %[4]s ` +issues.ref_pull_from=`于 %[2]s 引用合并请求 %[4]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` issues.author=作者 issues.author_helper=此用户是作者。 issues.role.owner=所有者 -issues.role.owner_helper=该用户是该仓库的所有者。 +issues.role.owner_helper=该用户是此仓库的所有者。 issues.role.member=成员 -issues.role.member_helper=该用户是拥有该仓库的组织成员。 +issues.role.member_helper=该用户是拥有此仓库的组织的成员。 issues.role.collaborator=协作者 issues.role.collaborator_helper=该用户已被邀请在仓库上进行协作。 issues.role.first_time_contributor=首次贡献者 -issues.role.first_time_contributor_helper=这是该用户对仓库的第一次贡献。 +issues.role.first_time_contributor_helper=这是该用户对此仓库的第一次贡献。 issues.role.contributor=贡献者 issues.role.contributor_helper=该用户之前提交过该仓库。 issues.re_request_review=再次请求审核 @@ -1592,7 +1675,7 @@ issues.label_exclusive_warning=在编辑工单或合并请求的标签时,任 issues.label_exclusive_order=排序顺序 issues.label_exclusive_order_tooltip=在同一个范围内的互斥标签将按照这个数字进行排序 issues.label_count=%d 个标签 -issues.label_open_issues=%d 个已打开工单/合并请求 +issues.label_open_issues=%d 个开启中工单 / 合并请求 issues.label_edit=编辑 issues.label_delete=删除 issues.label_modify=编辑标签 @@ -1616,18 +1699,19 @@ issues.lock=锁定对话 issues.unlock=解锁对话 issues.lock_duplicate=一个工单不能锁定两次。 issues.unlock_error=无法解锁一个未锁定的工单。 -issues.lock_with_reason=因为 %s 而锁定,并将对话限制为协作者 %s +issues.lock_with_reason=于 %s 锁定为 %s,并将对话限制为协作者 issues.lock_no_reason=锁定并限制仅协作者 %s issues.unlock_comment=解锁此对话 %s issues.lock_confirm=锁定 issues.unlock_confirm=解锁​​​​ +issues.lock.notice_1=- 其他用户不能对这个工单添加新的评论。 issues.lock.notice_2=- 您和仓库其他协作者仍可评论并可见。 issues.lock.notice_3=- 您可以在未来再次解锁这个工单。 issues.unlock.notice_1=- 每个人都可以再次就这一工单发表评论。 -issues.unlock.notice_2=- 您可以在未来再次解锁这个工单。 +issues.unlock.notice_2=- 您可以在未来再次锁定这个工单。 issues.lock.reason=锁定原因 -issues.lock.title=锁定有关此问题的对话。 -issues.unlock.title=解锁有关此问题的对话。 +issues.lock.title=锁定有关此工单的对话。 +issues.unlock.title=解锁有关此工单的对话。 issues.comment_on_locked=您不能对锁定的问题发表评论。 issues.delete=删除 issues.delete.title=是否删除工单? @@ -1654,72 +1738,78 @@ issues.stop_tracking_history=工作 %[1]s 于 %[2]s 停止 issues.cancel_tracking=取消 issues.cancel_tracking_history=`取消时间跟踪 %s` issues.del_time=删除此时间跟踪日志 -issues.add_time_history=已于 %[2]s 添加计时 %[1] +issues.add_time_history=于 %[2]s 添加计时 %[1] issues.del_time_history=`已删除时间 %s` issues.add_time_manually=手动添加时间 issues.add_time_hours=小时 issues.add_time_minutes=分钟 issues.add_time_sum_to_small=没有输入时间。 issues.time_spent_total=总用时 -issues.time_spent_from_all_authors=`总花费时间:%s` +issues.time_spent_from_all_authors=`总用时:%s` -issues.due_date=到期时间 -issues.invalid_due_date_format=到期时间的格式必须是「yyyy-mm-dd」的形式。 -issues.error_modifying_due_date=修改到期时间失败。 -issues.error_removing_due_date=删除到期时间失败。 -issues.push_commit_1=于 %[2]s 推送了 %[1]d 个提交 -issues.push_commits_n=于 %[2]s 推送了 %[1]d 个提交 -issues.force_push_codes=`于 %[6]s 强制推送 %[1]s,从 %[2]s,至 %[4]s` +issues.due_date=截止日期 +issues.invalid_due_date_format=截止日期的格式必须是「yyyy-mm-dd」的形式。 +issues.error_modifying_due_date=修改截止日期失败。 +issues.error_removing_due_date=删除截止日期失败。 +issues.push_commit_1=于 %[2]s 推送 %[1]d 个提交 +issues.push_commits_n=于 %[2]s 推送 %[1]d 个提交 +issues.force_push_codes=`于 %[6]s 强制推送 %[1]s,从 %[2]s 至 %[4]s` issues.force_push_compare=比较 issues.due_date_form=yyyy年mm月dd日 -issues.due_date_form_add=设置到期时间 +issues.due_date_form_add=设置截止日期 issues.due_date_form_edit=编辑 issues.due_date_form_remove=删除 -issues.due_date_not_set=未设置到期时间。 -issues.due_date_added=于 %[2]s 设置到期时间为 %[1]s -issues.due_date_modified=将到期日从 %[2]s 修改为 %[1]s %[3]s -issues.due_date_remove=于 %[2]s 删除了到期时间 %[1]s +issues.due_date_not_writer=您需要该仓库的写权限以更新工单的截止日期。 +issues.due_date_not_set=未设置截止日期。 +issues.due_date_added=于 %[2]s 设置截止日期为 %[1]s +issues.due_date_modified=于 %[3]s 将截止日期从 %[2]s 修改为 %[1]s +issues.due_date_remove=于 %[2]s 删除截止日期 %[1]s issues.due_date_overdue=过期 -issues.due_date_invalid=到期日期无效或超出范围。请使用 'yyyy-mm-dd' 格式。 +issues.due_date_invalid=截止日期无效或超出范围。请使用「yyyy-mm-dd」格式。 issues.dependency.title=依赖工单 -issues.dependency.issue_no_dependencies=没有设置依赖项。 -issues.dependency.pr_no_dependencies=没有设置依赖项。 +issues.dependency.issue_no_dependencies=未设置依赖工单。 +issues.dependency.pr_no_dependencies=未设置依赖工单。 issues.dependency.no_permission_1=您没有读取 %d 依赖关系的权限 issues.dependency.no_permission_n=您没有读取 %d 依赖关系的权限 issues.dependency.no_permission.can_remove=您没有读取此依赖关系的权限,但可以删除此依赖关系 -issues.dependency.add=添加依赖工单... +issues.dependency.add=添加依赖工单… issues.dependency.cancel=取消 issues.dependency.remove=删除 issues.dependency.remove_info=删除此依赖项 -issues.dependency.added_dependency=`添加了一个新的依赖项 %s` +issues.dependency.added_dependency=`添加了一个新依赖项 %s` issues.dependency.removed_dependency=`移除了一个依赖项 %s` -issues.dependency.pr_closing_blockedby=以下工单阻止了关闭此合并请求 +issues.dependency.pr_closing_blockedby=以下工单阻止关闭此合并请求 issues.dependency.issue_closing_blockedby=关闭此工单被以下工单阻止 -issues.dependency.issue_close_blocks=此工单阻止了以下工单的关闭 +issues.dependency.issue_close_blocks=此工单阻止以下工单的关闭 issues.dependency.pr_close_blocks=此合并请求阻止以下工单的关闭 +issues.dependency.issue_close_blocked=您需要关闭所有阻止此工单的工单后才能关闭它。 issues.dependency.issue_batch_close_blocked=无法批量关闭您所选择的工单,因为 #%d 工单仍然有处于打开状态的依赖工单 +issues.dependency.pr_close_blocked=您需要关闭所有阻止此合并请求的工单后才能合并它。 issues.dependency.blocks_short=阻止 issues.dependency.blocked_by_short=依赖于 issues.dependency.remove_header=删除依赖项 -issues.dependency.issue_remove_text=此操作将从工单中删除依赖。是否要继续? -issues.dependency.pr_remove_text=此操作将从合并请求中删除依赖。是否要继续? +issues.dependency.issue_remove_text=此操作将从工单中删除依赖。是否要继续? +issues.dependency.pr_remove_text=此操作将从合并请求中删除依赖。是否要继续? issues.dependency.setting=为工单和合并请求启用依赖 issues.dependency.add_error_same_issue=您不能让一个工单依赖于自身。 issues.dependency.add_error_dep_issue_not_exist=依赖项不存在。 issues.dependency.add_error_dep_not_exist=依赖项不存在。 issues.dependency.add_error_dep_exists=依赖项已存在。 +issues.dependency.add_error_cannot_create_circular=您无法在相互阻塞的工单之间建立依赖关系。 issues.dependency.add_error_dep_not_same_repo=这两个工单必须在同一仓库。 issues.review.self.approval=您不能批准您自己的合并请求。 issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。 issues.review.approve=于 %s 批准此合并请求 -issues.review.comment=评审于 %s +issues.review.comment=于 %s 评审 +issues.review.dismissed=于 %[2]s 取消 %[1]s 的评审 issues.review.dismissed_label=已取消 issues.review.left_comment=留下了一条评论 issues.review.content.empty=您需要留下一个注释,表明需要的更改。 issues.review.reject=请求变更 %s -issues.review.wait=已请求 %s 审核 +issues.review.wait=已请求 %s 评审 issues.review.add_review_request=于 %[2]s 请求 %[1]s 评审 issues.review.remove_review_request=取消对 %s 的评审请求 %s +issues.review.remove_review_request_self=拒绝评审 %s issues.review.pending=待定 issues.review.pending.tooltip=此评论目前对其他用户不可见。 若要提交您的待定评论,请在页面顶部选择 %s -> %s/%s/%s。 issues.review.review=评审 @@ -1741,6 +1831,7 @@ issues.review.requested=等待审核 issues.review.rejected=请求变更 issues.review.stale=批准后已更新 issues.review.unofficial=非官方审批数 +issues.assignee.error=因为未知原因,并非所有的指派都成功。 issues.reference_issue.body=内容 issues.content_history.deleted=已删除 issues.content_history.edited=已编辑 @@ -1748,7 +1839,7 @@ issues.content_history.created=已创建 issues.content_history.delete_from_history=从历史记录中删除 issues.content_history.delete_from_history_confirm=从历史记录中删除吗? issues.content_history.options=选项 -issues.reference_link=参考:%s +issues.reference_link=引用:%s compare.compare_base=基准分支 compare.compare_head=比较 @@ -1757,6 +1848,7 @@ pulls.desc=启用合并请求和代码评审。 pulls.new=创建合并请求 pulls.new.blocked_user=无法创建合并请求,因为您已被仓库所有者屏蔽。 pulls.new.must_collaborator=您必须是仓库的协作者才能创建合并请求。 +pulls.edit.already_changed=无法保存对合并请求的更改。其内容似乎已被其他用户更改。请刷新页面并重新编辑以避免覆盖他们的更改。 pulls.view=查看合并请求 pulls.compare_changes=创建合并请求 pulls.allow_edits_from_maintainers=允许维护者编辑 @@ -1777,11 +1869,13 @@ pulls.show_all_commits=显示所有提交 pulls.show_changes_since_your_last_review=显示自您上次审核以来的更改 pulls.showing_only_single_commit=仅显示提交 %[1]s 的更改 pulls.showing_specified_commit_range=仅显示 %[1]s..%[2]s 之间的更改 +pulls.select_commit_hold_shift_for_range=选择提交。按住 Shift + 单击选择一个范围 pulls.review_only_possible_for_full_diff=只有在查看全部差异时才能进行审核 pulls.filter_changes_by_commit=按提交筛选 pulls.nothing_to_compare=分支内容相同,无需创建合并请求。 +pulls.nothing_to_compare_have_tag=所选分支 / Git 标签相同。 pulls.nothing_to_compare_and_allow_empty_pr=这些分支是相等的,此合并请求将为空。 -pulls.has_pull_request=这些分支之间的合并请求已存在: %[2]s#%[3]d +pulls.has_pull_request=这些分支之间的合并请求已存在:%[2]s#%[3]d pulls.create=创建合并请求 pulls.title_desc=请求将 %[1]d 次代码提交从 %[2]s 合并至 %[3]s pulls.merged_title_desc=于 %[4]s 将 %[1]d 次代码提交从 %[2]s合并至 %[3]s @@ -1792,11 +1886,11 @@ pulls.tab_files=文件变动 pulls.reopen_to_merge=请重新创建此合并请求。 pulls.cant_reopen_deleted_branch=无法重新打开此合并请求,因为分支已删除。 pulls.merged=已合并 -pulls.merged_success=合并请求已成功合并和关闭 +pulls.merged_success=合并请求已成功合并并关闭 pulls.closed=合并请求已关闭 pulls.manually_merged=已手动合并 pulls.merged_info_text=分支 %s 现在可以删除了。 -pulls.is_closed=合并请求已经关闭。 +pulls.is_closed=合并请求已关闭。 pulls.title_wip_desc=`标题以 %s 开头以免合并请求意外合并。` pulls.cannot_merge_work_in_progress=此合并请求被标记为正在进行的工作。 pulls.still_in_progress=仍在进行中? @@ -1804,13 +1898,14 @@ pulls.add_prefix=添加 %s 前缀 pulls.remove_prefix=删除 %s 前缀 pulls.data_broken=此合并请求因为派生仓库信息缺失而中断。 pulls.files_conflicted=此合并请求有变更与目标分支冲突。 +pulls.is_checking=正在进行合并冲突检查… pulls.is_ancestor=此分支已经包含在目标分支中,没有什么可以合并。 pulls.is_empty=此分支上的更改已经在目标分支上。这将是一个空提交。 pulls.required_status_check_failed=一些必要的检查没有成功 pulls.required_status_check_missing=缺少一些必要的检查。 pulls.required_status_check_administrator=作为管理员,您仍可合并此合并请求 pulls.blocked_by_approvals=此合并请求还没有足够的批准。已获批准数 %d 个,需获批准数 %d 个。 -pulls.blocked_by_approvals_whitelisted=此合并请求还没有足够的批准。%[2]d 中的 %[1]d 个已由允许名单中的用户或团队批准。 +pulls.blocked_by_approvals_whitelisted=此合并请求尚未获得足够的批准。已获得 %d/%d 个来自允许列表中用户或团队的批准。 pulls.blocked_by_rejection=此合并请求有官方审核员请求的更改。 pulls.blocked_by_official_review_requests=此合并请求需要官方评审。 pulls.blocked_by_outdated_branch=此合并请求因过期而被阻止。 @@ -1827,12 +1922,16 @@ pulls.reject_count_1=%d 变更请求 pulls.reject_count_n=%d 变更请求 pulls.waiting_count_1=%d 个正在等待审核 pulls.waiting_count_n=%d 个正在等待审核 +pulls.wrong_commit_id=提交 id 必须在目标分支上 pulls.no_merge_desc=由于未启用合并选项,此合并请求无法合并。 pulls.no_merge_helper=在仓库设置中启用合并选项或者手工合并请求。 pulls.no_merge_wip=这个合并请求无法合并,因为被标记为尚未完成的工作。 +pulls.no_merge_not_ready=此合并请求尚未准备好合并,请检查审核状态和状态检查。 pulls.no_merge_access=您无权合并此合并请求。 pulls.merge_pull_request=创建合并提交 +pulls.rebase_merge_pull_request=变基后快进 +pulls.rebase_merge_commit_pull_request=变基后创建合并提交 pulls.squash_merge_pull_request=创建压缩提交 pulls.fast_forward_only_merge_pull_request=仅快进 pulls.merge_manually=手动合并 @@ -1840,13 +1939,20 @@ pulls.merge_commit_id=合并提交 ID pulls.require_signed_wont_sign=分支需要签名的提交,但这个合并将不会被签名 pulls.invalid_merge_option=您可以在此合并请求中使用合并选项。 +pulls.merge_conflict=合并失败:合并时有冲突发生。提示:采用其它合并策略。 pulls.merge_conflict_summary=错误信息 +pulls.rebase_conflict=合并失败:变基提交有冲突:%[1]s。提示:采用其它合并策略。 pulls.rebase_conflict_summary=错误信息 +pulls.unrelated_histories=合并失败:两个分支没有共同历史。提示:尝试不同的策略。 +pulls.merge_out_of_date=合并失败:在生成合并时,主分支已更新。提示:再试一次。 +pulls.head_out_of_date=合并失败:在生成合并时,head 已更新。提示:再试一次。 +pulls.has_merged=失败:合并请求已经合并。您不能再次合并或更改目标分支。 pulls.push_rejected=推送失败:推送被拒绝。审查此仓库的 Git 钩子。 pulls.push_rejected_summary=详细拒绝信息 -pulls.open_unmerged_pull_exists=`您不能执行重新打开操作, 因为已经存在相同的合并请求 (#%d)。` -pulls.status_checking=一些检测仍在等待运行 -pulls.status_checks_success=所有检测均成功 +pulls.push_rejected_no_message=推送失败:此推送被拒绝但未提供其他信息。请检查此仓库的 Git 钩子。 +pulls.open_unmerged_pull_exists=`您不能执行重新打开操作,因为已经存在相同的合并请求 (#%d)。` +pulls.status_checking=一些检查仍在等待运行 +pulls.status_checks_success=所有检查均成功 pulls.status_checks_warning=一些检查报告了警告 pulls.status_checks_failure=一些检查失败了 pulls.status_checks_error=一些检查报告了错误 @@ -1861,14 +1967,15 @@ pulls.update_not_allowed=您无权更新分支 pulls.outdated_with_base_branch=此分支相比基础分支已过期 pulls.close=关闭合并请求 pulls.closed_at=`于 %[2]s 关闭此合并请求 ` -pulls.reopened_at=`重新打开此合并请求 %[2]s` +pulls.reopened_at=`于 %[2]s 重新打开此合并请求` pulls.cmd_instruction_hint=查看命令行提示 pulls.cmd_instruction_checkout_title=检出 pulls.cmd_instruction_checkout_desc=从您的仓库中检出一个新的分支并测试变更。 pulls.cmd_instruction_merge_title=合并 pulls.cmd_instruction_merge_desc=合并变更并更新到 Gitea 上 -pulls.cmd_instruction_merge_warning=警告:此操作不能合并该合并请求,因为「自动检测手动合并」未启用 +pulls.cmd_instruction_merge_warning=警告:此操作不能合并该合并请求,因为「自动检查手动合并」未启用。 pulls.clear_merge_message=清除合并信息 +pulls.clear_merge_message_hint=清除合并消息只会删除提交消息内容,并保留生成的 Git 附加内容,如「Co-Authored-By…」。 pulls.auto_merge_button_when_succeed=(当检查成功时) pulls.auto_merge_when_succeed=在所有检查成功后自动合并 @@ -1880,12 +1987,12 @@ pulls.auto_merge_not_scheduled=此合并请求没有计划自动合并。 pulls.auto_merge_canceled_schedule=此合并请求的自动合并已取消。 pulls.auto_merge_newly_scheduled_comment=`已于 %[1]s 设置此合并请求在所有检查成功后自动合并` -pulls.auto_merge_canceled_schedule_comment=`已于 %[1]s 取消了自动合并设置 ` +pulls.auto_merge_canceled_schedule_comment=`已于 %[1]s 取消自动合并设置 ` pulls.delete.title=删除此合并请求? pulls.delete.text=您真的要删除这个合并请求吗?(这将永久删除所有内容。如果您打算将内容存档,请考虑关闭它) -pulls.recently_pushed_new_branches=您已经于%[2]s推送了分支 %[1]s +pulls.recently_pushed_new_branches=您已经于 %[2]s 推送分支 %[1]s pulls.upstream_diverging_prompt_behind_1=该分支落后于 %[2]s %[1]d 个提交 pulls.upstream_diverging_prompt_behind_n=该分支落后于 %[2]s %[1]d 个提交 pulls.upstream_diverging_prompt_base_newer=基础分支 %s 有新的更改 @@ -1910,7 +2017,7 @@ milestones.title=标题 milestones.desc=描述 milestones.due_date=截止日期(可选) milestones.clear=清除 -milestones.invalid_due_date_format=到期时间的格式必须是「yyyy-mm-dd」的形式。 +milestones.invalid_due_date_format=截止日期的格式必须是「yyyy-mm-dd」的形式。 milestones.create_success=里程碑「%s」创建成功。 milestones.edit=编辑里程碑 milestones.edit_subheader=里程碑组织工单,合并请求和跟踪进度。 @@ -1929,10 +2036,12 @@ milestones.filter_sort.most_issues=工单从多到少 milestones.filter_sort.least_issues=工单从少到多 signing.will_sign=这个提交将用密钥「%s」签名。 +signing.wont_sign.error=在检查提交是否可以被签名时出错。 signing.wont_sign.nokey=没有可用的密钥来签署这个提交。 signing.wont_sign.never=提交从未签名。 signing.wont_sign.always=提交总是签名。 signing.wont_sign.pubkey=由于您没有公钥关联到您的账户,提交将不会被签名。 +signing.wont_sign.twofa=您必须启用两步验证才能签名提交。 signing.wont_sign.parentsigned=提交将不会被签名,因为父提交没有签名。 signing.wont_sign.basesigned=合并将不会被签名,因为父提交没有签名。 signing.wont_sign.headsigned=合并将不会被签名,因为最新提交没有签名。 @@ -1945,7 +2054,7 @@ ext_wiki.desc=链接到外部百科。 wiki=百科 wiki.welcome=欢迎来到百科。 -wiki.welcome_desc=百科允许您撰写和与协作者分享文档。 +wiki.welcome_desc=百科允许您撰写并与协作者分享文档。 wiki.desc=撰写和与协作者分享文档 wiki.create_first_page=创建第一个页面 wiki.page=页面 @@ -1963,11 +2072,11 @@ wiki.wiki_page_revisions=页面历史 wiki.back_to_wiki=返回百科 wiki.delete_page_button=删除页面 wiki.delete_page_notice_1=百科页面「%s」删除后无法恢复,是否继续? -wiki.page_already_exists=相同名称的 Wiki 页面已经存在。 +wiki.page_already_exists=相同名称的百科页面已经存在。 wiki.reserved_page=百科页面名称「%s」是保留的。 wiki.pages=所有页面 wiki.last_updated=最后更新于 %s -wiki.page_name_desc=输入此百科页面的名称。特殊名称有:「Home」,「_Sidebar」和「_Footer」。 +wiki.page_name_desc=输入此百科页面的名称。特殊名称有:「Home」、「_Sidebar」和「_Footer」。 wiki.original_git_entry_tooltip=查看原始的 Git 文件而不是使用友好链接。 activity=活动 @@ -1988,13 +2097,13 @@ activity.active_prs_count_1=%d 个合并请求 activity.active_prs_count_n=%d 个合并请求 activity.merged_prs_count_1=已合并的合并请求 activity.merged_prs_count_n=已合并的合并请求 -activity.opened_prs_count_1=创建的合并请求 -activity.opened_prs_count_n=创建的合并请求 +activity.opened_prs_count_1=已创建的合并请求 +activity.opened_prs_count_n=已创建的合并请求 activity.title.user_1=%d 位用户 activity.title.user_n=%d 位用户 activity.title.prs_1=%d 个合并请求 activity.title.prs_n=%d 个合并请求 -activity.title.prs_merged_by=%[2]s 由 %[1]s 合并 +activity.title.prs_merged_by=%[2]s 合并了 %[1]s activity.title.prs_opened_by=%[2]s 创建了 %[1]s activity.merged_prs_label=已合并 activity.opened_prs_label=已创建 @@ -2004,20 +2113,21 @@ activity.closed_issues_count_1=已关闭的工单 activity.closed_issues_count_n=已关闭的工单 activity.title.issues_1=%d 张工单 activity.title.issues_n=%d 张工单 -activity.title.issues_closed_from=%s 从 %s 关闭 +activity.title.issues_closed_from=%[2]s 关闭了 %[1]s activity.title.issues_created_by=%[2]s 创建了 %[1]s activity.closed_issue_label=已关闭 -activity.new_issues_count_1=已打开的工单 +activity.new_issues_count_1=开启的工单 activity.new_issues_count_n=已打开的工单 activity.new_issue_label=打开的 activity.title.unresolved_conv_1=%d 未解决的会话 activity.title.unresolved_conv_n=%d 未解决的会话 activity.unresolved_conv_desc=这些最近更新的工单和合并请求还没有解决。 activity.unresolved_conv_label=打开 -activity.title.releases_1=%d 个发布 -activity.title.releases_n=%d 个发布 +activity.title.releases_1=%d 个版本 +activity.title.releases_n=%d 个版本 activity.title.releases_published_by=%[2]s 发布了 %[1]s activity.published_release_label=已发布 +activity.no_git_activity=在此期间没有任何提交活动。 activity.git_stats_exclude_merges=排除合并后, activity.git_stats_author_1=%d 位作者 activity.git_stats_author_n=%d 位作者 @@ -2045,11 +2155,13 @@ contributors.contribution_type.additions=新增 contributors.contribution_type.deletions=删除 settings=设置 +settings.desc=设置是您可以管理仓库设置的地方。 settings.options=仓库 settings.public_access=公开访问 settings.public_access_desc=配置公共访客访问权限以覆盖此仓库的默认值。 settings.public_access.docs.not_set=未设置:没有额外的公共访问权限。访客权限遵循仓库的可见性和成员权限。 settings.public_access.docs.anonymous_read=匿名可读:未登录的用户可以通过读取权限访问单元。 +settings.public_access.docs.everyone_read=所有人可读:所有登录用户都可以通过读取权限访问单元。读取问题/拉取请求单元的权限也意味着用户可以创建新的问题/拉取请求。 settings.public_access.docs.everyone_write=所有人可写:所有登录用户都有写入权限。只有百科支持此权限。 settings.collaboration=协作者 settings.collaboration.admin=管理员 @@ -2062,11 +2174,12 @@ settings.hooks=Web 钩子 settings.githooks=管理 Git 钩子 settings.basic_settings=基本设置 settings.mirror_settings=镜像设置 -settings.mirror_settings.docs=将您的仓库设置为自动同步另一个仓库的提交、标签和分支。 -settings.mirror_settings.docs.disabled_pull_mirror.instructions=将您的项目设置为自动将提交、标签和分支推送到另一个仓库。您的站点管理员已禁用了拉取镜像。 -settings.mirror_settings.docs.disabled_push_mirror.instructions=将您的项目设置为自动从一个仓库拉取提交、标签和分支。 +settings.mirror_settings.docs=将您的仓库设置为自动同步另一个仓库的提交、Git 标签和分支。 +settings.mirror_settings.docs.disabled_pull_mirror.instructions=将您的项目设置为自动将提交、Git 标签和分支推送到另一个仓库。您的站点管理员已禁用了拉取镜像。 +settings.mirror_settings.docs.disabled_push_mirror.instructions=将您的项目设置为自动从一个仓库拉取提交、Git 标签和分支。 settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=现在,这只能在「迁移外部仓库」菜单中完成。欲了解更多信息,请参考: settings.mirror_settings.docs.disabled_push_mirror.info=您的站点管理员已禁用推送镜像。 +settings.mirror_settings.docs.no_new_mirrors=您的仓库将镜像同步另一个仓库的更改。请注意,您目前无法创建任何新的镜像。 settings.mirror_settings.docs.can_still_use=虽然您不能修改现有镜像或创建新镜像,但您仍然可以使用已存在的镜像。 settings.mirror_settings.docs.pull_mirror_instructions=要创建一个拉取镜像,请参阅: settings.mirror_settings.docs.more_information_if_disabled=您可以在这里找到更多关于推送和拉取镜像的信息: @@ -2116,12 +2229,12 @@ settings.tracker_issue_style.alphanumeric=英文字母数字组合形式 settings.tracker_issue_style.regexp=正则表达式 settings.tracker_issue_style.regexp_pattern=正则表达式 settings.tracker_issue_style.regexp_pattern_desc=第一个被捕获的组将取代 {index}。 -settings.tracker_url_format_desc=使用占位符 {user}, {repo} 和 {index} 作为用户名、仓库名和工单索引。 +settings.tracker_url_format_desc=使用占位符 {user}、{repo} 和 {index} 作为用户名、仓库名和工单索引。 settings.enable_timetracker=启用时间跟踪 settings.allow_only_contributors_to_track_time=仅允许成员跟踪时间 settings.pulls_desc=启用合并请求 settings.pulls.ignore_whitespace=忽略空白冲突 -settings.pulls.enable_autodetect_manual_merge=启用自动检测手动合并 (注意:在某些特殊情况下可能发生错误判断) +settings.pulls.enable_autodetect_manual_merge=启用自动检查手动合并(注意:在某些特殊情况下可能会出现误判) settings.pulls.allow_rebase_update=允许通过变基更新合并请求分支 settings.pulls.default_delete_branch_after_merge=默认合并后删除合并请求分支 settings.pulls.default_allow_edits_from_maintainers=默认允许维护者编辑 @@ -2141,6 +2254,7 @@ settings.admin_indexer_commit_sha=上次索引的 SHA settings.admin_indexer_unindexed=未索引 settings.reindex_button=添加到重新索引队列 settings.reindex_requested=已请求重新索引 +settings.admin_enable_close_issues_via_commit_in_any_branch=通过在非默认分支中提交来关闭工单 settings.danger_zone=危险操作区 settings.new_owner_has_same_repo=新的仓库拥有者已经存在同名仓库! settings.convert=转换为普通仓库 @@ -2162,6 +2276,7 @@ settings.transfer_abort_invalid=您不能取消不存在的仓库转移。 settings.transfer_abort_success=成功取消将仓库转移给 %s。 settings.transfer_desc=您可以将仓库转移至您拥有管理员权限的帐户或组织。 settings.transfer_form_title=输入仓库名称以确认: +settings.transfer_in_progress=当前正在进行转移。 如果您想将此仓库转移给另一个用户,请取消它。 settings.transfer_notices_1=- 如果将此仓库转移给其他用户,您将失去对此仓库的访问权限。 settings.transfer_notices_2=- 如果将其转移到您(共同)拥有的组织,您可以继续访问该仓库。 settings.transfer_notices_3=- 如果仓库是私有的并且被转移给某个用户,那么此操作可以确保该用户至少具有读权限(以及必要时的更改权限)。 @@ -2176,17 +2291,22 @@ settings.trust_model.default=默认信任模型 settings.trust_model.default.desc=为此安装使用默认仓库信任模型。 settings.trust_model.collaborator=协作者 settings.trust_model.collaborator.long=协作者:信任协作者的签名 +settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为「可信」(无论它们是否是提交者),签名只符合提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。 settings.trust_model.committer=提交者 +settings.trust_model.committer.long=提交者: 信任与提交者相符的签名(这符合 GitHub 的行为并将强制 Gitea 签名的提交以 Gitea 为提交者)。 +settings.trust_model.committer.desc=有效签名只有和提交者相匹配才会被标记为「受信任」,否则它们将被标记为「不匹配」。这强制 Gitea 成为签名提交的提交者,而实际提交者被加上 Co-authored-by: 和 Co-committed-by: 的标记。 默认的 Gitea 密钥必须匹配数据库中的一名用户。 settings.trust_model.collaboratorcommitter=协作者+提交者 settings.trust_model.collaboratorcommitter.long=协作者+提交者:信任协作者同时是提交者的签名 +settings.trust_model.collaboratorcommitter.desc=此仓库中协作者的有效签名在他同时是提交者时将被标记为「可信」,签名只匹配了提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。这会强制 Gitea 成为签名者和提交者,实际的提交者将被标记于提交消息结尾处的「Co-Authored-By:」和「Co-Committed-By:」。默认的 Gitea 签名密钥必须匹配数据库中的一个用户密钥。 settings.wiki_delete=删除百科数据 settings.wiki_delete_desc=删除仓库百科数据是永久性的,无法撤消。 settings.wiki_delete_notices_1=- 这将永久删除和禁用 %s 的百科。 settings.confirm_wiki_delete=删除百科数据 settings.wiki_deletion_success=仓库百科数据删除成功! settings.delete=删除本仓库 -settings.delete_desc=删除仓库是永久性的, 无法撤消。 +settings.delete_desc=删除仓库是永久性的,无法撤消。 settings.delete_notices_1=- 此操作 无法 被回滚。 +settings.delete_notices_2=- 此操作将永久删除仓库 %s,包括代码、 工单、评论、百科数据和协作者设置。 settings.delete_notices_fork_1=- 在此仓库删除后,它的派生仓库将变成独立仓库。 settings.deletion_success=仓库已删除。 settings.update_settings_success=仓库设置已更新。 @@ -2208,7 +2328,9 @@ settings.team_not_in_organization=团队不在与仓库相同的组织中 settings.teams=团队 settings.add_team=添加团队 settings.add_team_duplicate=团队已经拥有仓库 -settings.delete_team_tip=该团队仍有仓库, 无法删除 +settings.add_team_success=团队现在可以访问仓库。 +settings.change_team_permission_tip=团队权限设置于团队设置页面,不能根据仓库更改 +settings.delete_team_tip=该团队仍有仓库,无法删除 settings.remove_team_success=团队访问仓库的权限已删除。 settings.add_webhook=添加 Web 钩子 settings.add_webhook.invalid_channel_name=Web 钩子通道名称不能为空且不能仅包含一个 # 字符。 @@ -2246,12 +2368,12 @@ settings.discord_icon_url=图标 URL settings.event_desc=触发条件: settings.event_push_only=推送事件 settings.event_send_everything=所有事件 -settings.event_choose=自定义事件... +settings.event_choose=自定义事件… settings.event_header_repository=仓库事件 settings.event_create=创建 -settings.event_create_desc=创建分支或标签 +settings.event_create_desc=分支或 Git 标签已创建。 settings.event_delete=刪除 -settings.event_delete_desc=分支或标签已删除。 +settings.event_delete_desc=分支或 Git 标签已删除。 settings.event_fork=派生 settings.event_fork_desc=仓库已派生。 settings.event_wiki=百科 @@ -2303,7 +2425,7 @@ settings.event_workflow_job_desc=Gitea 工作流队列中、等待中、正在 settings.event_package=软件包 settings.event_package_desc=软件包在仓库中已创建或删除。 settings.branch_filter=分支过滤 -settings.branch_filter_desc=推送、创建,删除分支事件的分支白名单,使用 glob 表达式匹配指定。若为空或 *,则会报告所有分支的事件。语法文档见 %[2]s。示例:master,{master,release*}。 +settings.branch_filter_desc=推送、创建,删除分支事件的分支白名单,使用 glob 表达式匹配指定。若为空或 *,则会报告所有分支的事件。语法文档见 %[2]s。示例:master、{master,release*}。 settings.authorization_header=授权标头 settings.authorization_header_desc=当存在时将被作为授权标头包含在内。例如: %s。 settings.active=激活 @@ -2406,9 +2528,9 @@ settings.protect_branch_name_pattern=受保护的分支名称表达式 settings.protect_branch_name_pattern_desc=分支保护的名称匹配表达式。语法请参阅 文档 。如:main, release/** settings.protect_patterns=表达式 settings.protect_protected_file_patterns=受保护的文件表达式(使用分号「;」分隔): -settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。 可以使用分号「;」分隔多个表达式。 见%[2]s文档了解表达式语法。例如: .drone.yml, /docs/**/*.txt。 +settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。可以使用分号(';')分隔多个表达式。见 %[2]s 文档了解表达式语法。例如:.drone.yml、/docs/**/*.txt。 settings.protect_unprotected_file_patterns=不受保护的文件表达式(使用分号「;」分隔): -settings.protect_unprotected_file_patterns_desc=如果用户有写权限,则允许直接更改的不受保护的文件,以绕过推送限制。可以使用分号分隔多个表达式「;」。 见 %[2]s 文档了解表达式语法。例如: .drone.yml, /docs/**/*.txt。 +settings.protect_unprotected_file_patterns_desc=如果用户具有写权限则允许直接更改的不受保护文件,可绕过推送限制。可使用分号(';')分隔多个表达式。见 %[2]s 文档了解表达式语法。例如:.drone.yml、/docs/**/*.txt。 settings.add_protected_branch=启用保护 settings.delete_protected_branch=禁用保护 settings.update_protect_branch_success=分支保护规则「%s」更新成功。 @@ -2423,25 +2545,26 @@ settings.block_on_official_review_requests_desc=处于评审状态时,即使 settings.block_outdated_branch=如果合并请求已经过时,阻止合并 settings.block_outdated_branch_desc=当头部分支落后基础分支时,不能合并。 settings.block_admin_merge_override=管理员须遵守分支保护规则 +settings.block_admin_merge_override_desc=管理员须遵守分支保护规则,不能规避该规则。 settings.default_branch_desc=请选择一个默认的分支用于合并请求和提交: settings.merge_style_desc=合并方式 settings.default_merge_style_desc=默认合并风格 -settings.choose_branch=选择一个分支... +settings.choose_branch=选择一个分支… settings.no_protected_branch=没有受保护的分支 settings.edit_protected_branch=编辑 settings.protected_branch_required_rule_name=必须填写规则名称 settings.protected_branch_duplicate_rule_name=规则名称已存在 settings.protected_branch_required_approvals_min=所需的审批数不能为负数。 -settings.tags=标签 -settings.tags.protection=标签保护 -settings.tags.protection.pattern=标签表达式 +settings.tags=Git 标签 +settings.tags.protection=Git 标签保护 +settings.tags.protection.pattern=Git 标签表达式 settings.tags.protection.allowed=允许列表 settings.tags.protection.allowed.users=允许的账号 settings.tags.protection.allowed.teams=允许的团队 settings.tags.protection.allowed.noone=无 -settings.tags.protection.create=保护标签 -settings.tags.protection.none=没有受保护的标签。 -settings.tags.protection.pattern.description=您可以使用单个名称或 glob 表达式匹配或正则表达式来匹配多个标签。了解详情请访问 保护标签指南。 +settings.tags.protection.create=保护 Git 标签 +settings.tags.protection.none=没有受保护的 Git 标签。 +settings.tags.protection.pattern.description=您可以使用单个名称或 glob 表达式匹配或正则表达式来匹配多个 Git 标签。了解详情请访问 保护标签指南。 settings.bot_token=Bot 令牌 settings.chat_id=聊天 ID settings.thread_id=线程 ID @@ -2449,7 +2572,10 @@ settings.matrix.homeserver_url=主服务器网址 settings.matrix.room_id=房间ID settings.matrix.message_type=消息类型 settings.visibility.private.button=设为私有 +settings.visibility.private.text=将可见性更改为私有会使仓库仅对允许的成员可见,而且可能会消除它与派生仓库、关注者和点赞之间的关系。 settings.visibility.private.bullet_title=将可见性改为私有将会: +settings.visibility.private.bullet_one=使仓库只对允许的成员可见。 +settings.visibility.private.bullet_two=可能会删除它与 派生仓库、 关注者和 点赞 之间的关系。 settings.visibility.public.button=设为公开 settings.visibility.public.text=将可见性更改为公开会使任何人都可见。 settings.visibility.public.bullet_title=将可见性改为公开将会: @@ -2459,15 +2585,16 @@ settings.visibility.error=试图更改仓库可见性时出错。 settings.visibility.fork_error=无法更改派生仓库的可见性。 settings.archive.button=归档仓库 settings.archive.header=归档此仓库 -settings.archive.text=归档仓库将使其完全只读。它将在首页隐藏。没有人(包括您)能够进行新的提交,或打开工单及合并请求。 +settings.archive.text=归档仓库将使其完全只读。它将在首页隐藏。没有人(包括您)能够进行新的提交,或创建工单及合并请求。 settings.archive.success=仓库已成功归档。 settings.archive.error=仓库在归档时出现异常。请通过日志获取详细信息。 settings.archive.error_ismirror=请不要对镜像仓库归档,谢谢! settings.archive.branchsettings_unavailable=已归档仓库无法进行分支设置。 -settings.archive.tagsettings_unavailable=已归档仓库的标签设置不可用。 +settings.archive.tagsettings_unavailable=已归档仓库的 Git 标签设置不可用。 settings.archive.mirrors_unavailable=如果仓库已归档,镜像将不可用。 settings.unarchive.button=撤销仓库归档 settings.unarchive.header=撤销此仓库归档 +settings.unarchive.text=撤销归档将恢复仓库接收提交、推送,以及新工单和合并请求的能力。 settings.unarchive.success=仓库已成功撤销归档。 settings.unarchive.error=仓库在取消归档时出现异常。请通过日志获取详细信息。 settings.update_avatar_success=仓库头像已经更新。 @@ -2485,9 +2612,11 @@ settings.lfs_invalid_locking_path=无效路径:%s settings.lfs_invalid_lock_directory=无法锁定目录:%s settings.lfs_lock_already_exists=锁已经存在:%s settings.lfs_lock=锁定 +settings.lfs_lock_path=要锁定的文件路径… settings.lfs_locks_no_locks=无锁定 settings.lfs_lock_file_no_exist=锁定的文件在默认分支中不存在 settings.lfs_force_unlock=强制解锁 +settings.lfs_pointers.found=找到 %d 个块指针 — %d 个关联, %d 个未关联(%d 个从仓库丢失) settings.lfs_pointers.sha=Blob SHA settings.lfs_pointers.oid=OID settings.lfs_pointers.inRepo=在仓库中 @@ -2560,9 +2689,9 @@ diff.submodule_deleted=子模块 %[1]s 已从 %[2]s 中删除 diff.submodule_updated=子模块 %[1]s 已更新:%[2]s releases.desc=跟踪项目版本和下载。 -release.releases=发布 +release.releases=版本发布 release.detail=发布详情 -release.tags=标签 +release.tags=Git 标签 release.new_release=发布新版 release.draft=草稿 release.prerelease=预发布 @@ -2571,16 +2700,16 @@ release.latest=最新 release.compare=比较 release.edit=编辑 release.ahead.commits=%d 次提交 -release.ahead.target=在此版本发布后已加入到 %s -tag.ahead.target=自此标签到 %s +release.ahead.target=在此版本后已推送到 %s +tag.ahead.target=自此 Git 标签到 %s release.source_code=源代码 release.new_subheader=发布组织项目的版本。 release.edit_subheader=发布组织项目的版本。 -release.tag_name=标签名称 +release.tag_name=Git 标签名称 release.target=目标分支 -release.tag_helper=选择一个存在的标签或者创建新标签。 -release.tag_helper_new=新标签。此标签将从目标创建。 -release.tag_helper_existing=现有标签。 +release.tag_helper=选择一个存在的 Git 标签或者创建新 Git 标签。 +release.tag_helper_new=新 Git 标签。此 Git 标签将从目标创建。 +release.tag_helper_existing=现有 Git 标签。 release.title=发布标题 release.title_empty=标题不能为空。 release.message=描述这个版本 @@ -2591,22 +2720,22 @@ release.publish=发布版本 release.save_draft=保存草稿 release.edit_release=保存此次发布 release.delete_release=删除发布 -release.delete_tag=删除标签 +release.delete_tag=删除 Git 标签 release.deletion=删除发布 release.deletion_desc=删除发布只会从 Gitea 中移除发布。这不会影响 Git 的标签以及您仓库的内容和历史。是否继续? release.deletion_success=该发布已删除。 -release.deletion_tag_desc=将从仓库中删除此标签。仓库内容和历史记录保持不变。继续吗? -release.deletion_tag_success=该标签已删除。 -release.tag_name_already_exist=使用此标签名称的发布已经存在。 -release.tag_name_invalid=标签名称无效。 -release.tag_name_protected=标签名已受保护。 -release.tag_already_exist=此标签名已存在。 +release.deletion_tag_desc=将从仓库中删除此 Git 标签。仓库内容和历史记录保持不变。继续吗? +release.deletion_tag_success=该 Git 标签已删除。 +release.tag_name_already_exist=使用此 Git 标签名称的发布已经存在。 +release.tag_name_invalid=Git 标签名称无效。 +release.tag_name_protected=Git 标签名已受保护。 +release.tag_already_exist=此 Git 标签名已存在。 release.downloads=下载附件 release.download_count=下载:%s -release.add_tag_msg=使用发布的标题和内容作为标签消息。 -release.add_tag=仅创建标签 +release.add_tag_msg=使用发布的标题和内容作为 Git 标签消息。 +release.add_tag=仅创建 Git 标签 release.releases_for=%s 的发布 -release.tags_for=%s 的标签 +release.tags_for=%s 的 Git 标签 branch.name=分支名称 branch.already_exists=名为「%s」的分支已存在。 @@ -2622,7 +2751,7 @@ branch.create_from=从「%s」 branch.create_success=分支「%s」已创建。 branch.branch_already_exists=此仓库已存在名为「%s」的分支。 branch.branch_name_conflict=分支名称「%s」与已存在的分支「%s」冲突。 -branch.tag_collision=分支「%s」无法创建,因为同名的标签已经存在。 +branch.tag_collision=分支「%s」无法创建,因为同名的 Git 标签已经存在。 branch.deleted_by=删除人:%s branch.restore_success=分支「%s」已还原。 branch.restore_failed=分支「%s」还原失败。 @@ -2645,14 +2774,15 @@ branch.new_branch_from=基于「%s」创建新分支 branch.renamed=分支 %s 已重命名为 %s。 branch.rename_default_or_protected_branch_error=只有管理员能重命名默认分支和受保护的分支。 branch.rename_protected_branch_failed=此分支受到 glob 语法规则的保护。 +branch.commits_divergence_from=提交分歧:落后 %[3]s %[1]d 个提交,领先 %[2]d 个提交 branch.commits_no_divergence=与分支 %[1]s 相同 -tag.create_tag=创建标签 %s -tag.create_tag_operation=创建标签 -tag.confirm_create_tag=创建标签 -tag.create_tag_from=基于「%s」创建新标签 +tag.create_tag=创建 Git 标签 %s +tag.create_tag_operation=创建 Git 标签 +tag.confirm_create_tag=创建 Git 标签 +tag.create_tag_from=基于「%s」创建新 Git 标签 -tag.create_success=标签「%s」已存在。 +tag.create_success=Git 标签「%s」已存在。 topic.manage_topics=管理主题 topic.done=保存 @@ -2669,6 +2799,7 @@ error.csv.invalid_field_count=无法渲染此文件,因为它在第 %d 行中 error.broken_git_hook=此仓库的 Git 钩子似乎已损坏。 请按照 文档 来修复它们,然后推送一些提交来刷新状态。 [graphs] +component_loading=正在加载 %s… component_loading_failed=无法加载 %s component_loading_info=这可能需要一点时间… component_failed_to_load=意外的错误发生了。 @@ -2697,7 +2828,7 @@ team_desc_helper=描述团队的目的或作用。 team_access_desc=仓库权限 team_permission_desc=权限 team_unit_desc=允许访问仓库单元 -team_unit_disabled=(已禁用) +team_unit_disabled=(已禁用) form.name_been_taken=组织名称「%s」已经被占用。 form.name_reserved=组织名称「%s」是保留的。 @@ -2707,6 +2838,7 @@ form.create_org_not_allowed=此账号禁止创建组织 settings=组织设置 settings.options=组织 settings.full_name=组织全名 +settings.email=联系邮箱 settings.website=网站 settings.location=所在地区 settings.permission=权限 @@ -2723,7 +2855,10 @@ settings.update_setting_success=组织设置已更新。 settings.rename=修改组织名称 settings.rename_desc=更改组织名称同时会更改组织的 URL 地址并释放旧的名称。 +settings.rename_success=组织 %[1]s 已成功重命名为 %[2]s。 +settings.rename_no_change=组织名称没有变更。 settings.rename_new_org_name=新组织名称 +settings.rename_failed=由于内部错误,重命名组织失败 settings.rename_notices_1=此操作 无法 被回滚。 settings.rename_notices_2=在被人使用前,旧名称将会被重定向。 @@ -2733,9 +2868,11 @@ settings.delete_account=删除当前组织 settings.delete_prompt=删除操作会永久清除该组织的信息,并且 无法 恢复! settings.name_confirm=输入组织名称以确认: settings.delete_notices_1=此操作 无法 被回滚。 +settings.delete_notices_2=此操作将永久删除 %s 的所有仓库,包括 Git 数据、 工单、评论、百科和协作者的操作权限。 settings.delete_notices_3=此操作将永久删除 %s 的所有 软件包。 settings.delete_notices_4=此操作将永久删除 %s 的所有 项目。 settings.confirm_delete_account=确认删除组织 +settings.delete_failed=由于内部错误,删除组织失败 settings.delete_successful=组织 %s 已成功删除。 settings.hooks_desc=在此处添加的 Web 钩子将会应用到该组织下的 所有仓库。 @@ -2792,6 +2929,7 @@ teams.remove_all_repos_title=移除所有团队仓库 teams.remove_all_repos_desc=这将从团队中移除所有仓库。 teams.add_all_repos_title=添加所有仓库 teams.add_all_repos_desc=这将把组织的所有仓库添加到团队。 +teams.add_nonexistent_repo=您尝试添加的仓库不存在,请先创建它。 teams.add_duplicate_users=用户已经是团队成员。 teams.repos.none=此团队无法访问任何仓库。 teams.members.none=团队中没有成员。 @@ -2832,6 +2970,7 @@ repositories=仓库管理 hooks=Web 钩子 integrations=集成 authentication=认证源 +emails=用户邮箱 config=应用配置 config_summary=摘要 config_settings=设置 @@ -2863,19 +3002,28 @@ dashboard.cron.cancelled=计划任务:%[1]s 已取消:%[3]s dashboard.cron.error=计划任务错误: %s: %[3]s dashboard.cron.finished=计划任务:%[1]s 已完成 dashboard.delete_inactive_accounts=删除所有未激活的帐户 +dashboard.delete_inactive_accounts.started=删除所有未激活的账号任务已启动。 dashboard.delete_repo_archives=删除所有仓库的存档(ZIP、TAR、GZ等) +dashboard.delete_repo_archives.started=删除所有仓库存档任务已启动。 dashboard.delete_missing_repos=删除所有丢失 Git 文件的仓库 +dashboard.delete_missing_repos.started=删除所有丢失 Git 文件的仓库任务已启动。 dashboard.delete_generated_repository_avatars=删除生成的仓库头像 dashboard.sync_repo_branches=将缺少的分支从 Git 数据同步到数据库 -dashboard.sync_repo_tags=从 Git 数据同步标签到数据库 +dashboard.sync_repo_tags=从 Git 数据同步 Git 标签到数据库 dashboard.update_mirrors=更新镜像仓库 dashboard.repo_health_check=健康检查所有仓库 dashboard.check_repo_stats=检查所有仓库统计 dashboard.archive_cleanup=删除旧的仓库存档 +dashboard.deleted_branches_cleanup=清理已删除的分支 dashboard.update_migration_poster_id=更新迁移的发表者ID +dashboard.git_gc_repos=对仓库进行垃圾回收 +dashboard.resync_all_sshkeys=使用 Gitea 的 SSH 密钥更新「.ssh/authorized_keys」文件。 +dashboard.resync_all_sshprincipals=使用 Gitea 的 SSH 规则更新「.ssh/authorized_principals」文件。 +dashboard.resync_all_hooks=重新同步所有仓库的 pre-receive、update 和 post-receive 钩子 dashboard.reinit_missing_repos=重新初始化所有丢失的 Git 仓库存在的记录 dashboard.sync_external_users=同步外部用户数据 dashboard.cleanup_hook_task_table=清理 hook_task 表 +dashboard.cleanup_packages=清理过期的软件包 dashboard.cleanup_actions=清理过期的工作流资源 dashboard.server_uptime=服务运行时间 dashboard.current_goroutine=当前 Goroutines 数量 @@ -2907,14 +3055,16 @@ dashboard.total_gc_pause=GC 暂停时间总量 dashboard.last_gc_pause=上次 GC 暂停时间 dashboard.gc_times=GC 执行次数 dashboard.delete_old_actions=从数据库中删除所有旧工作流记录 +dashboard.delete_old_actions.started=已开始从数据库中删除所有旧工作流记录。 dashboard.update_checker=更新检查器 dashboard.delete_old_system_notices=从数据库中删除所有旧系统通知 +dashboard.gc_lfs=垃圾回收 LFS 元数据 dashboard.stop_zombie_tasks=停止僵尸工作流任务 dashboard.stop_endless_tasks=停止无限循环的工作流任务 dashboard.cancel_abandoned_jobs=取消已放弃的工作流任务 dashboard.start_schedule_tasks=启动工作流计划任务 dashboard.sync_branch.started=分支同步已开始 -dashboard.sync_tag.started=标签同步已开始 +dashboard.sync_tag.started=Git 标签同步已开始 dashboard.rebuild_issue_indexer=重建工单索引 dashboard.sync_repo_licenses=重新探测仓库许可证 @@ -2932,6 +3082,7 @@ users.2fa=两步验证 users.repos=仓库数 users.created=创建时间 users.last_login=上次登录 +users.never_login=从未登录 users.send_register_notify=发送注册通知 users.new_success=用户账户「%s」已创建。 users.edit=修改 @@ -2943,7 +3094,7 @@ users.update_profile_success=该帐户已更新。 users.edit_account=编辑帐号 users.max_repo_creation=最大仓库数 users.max_repo_creation_desc=(设置为 -1 表示使用全局默认值) -users.is_activated=该用户已激活 +users.is_activated=用户已激活 users.prohibit_login=禁用登录 users.is_admin=是管理员 users.is_restricted=受限 @@ -2958,6 +3109,7 @@ users.still_own_repo=此用户仍然拥有一个或多个仓库。必须首先 users.still_has_org=此用户是组织的成员。必须先从组织中删除用户。 users.purge=清理用户 users.purge_help=强制删除用户和用户拥有的任何仓库、组织和软件包。所有评论也将删除。 +users.still_own_packages=此用户仍然拥有一个或多个软件包,请先删除这些软件包。 users.deletion_success=用户帐户已删除。 users.reset_2fa=重置两步验证 users.list_status_filter.menu_text=过滤 @@ -2975,9 +3127,13 @@ users.list_status_filter.not_2fa_enabled=未启用 2FA users.details=用户详细信息 emails.email_manage_panel=邮件管理 -emails.primary=主要的 +emails.primary=主 emails.activated=已激活 +emails.filter_sort.email=邮箱 +emails.filter_sort.email_reverse=邮箱(倒序) emails.filter_sort.name=用户名 +emails.filter_sort.name_reverse=用户名(倒序) +emails.updated=邮箱已更新 emails.not_updated=无法更新请求的邮箱地址:%v emails.duplicate_active=此邮箱地址已被另一个用户激活使用。 emails.change_email_header=更新邮箱属性 @@ -2985,6 +3141,7 @@ emails.change_email_text=您确定要更新该邮箱地址吗? emails.delete=删除邮箱 emails.delete_desc=您确定要删除该邮箱地址? emails.deletion_success=邮箱地址已删除。 +emails.delete_primary_email_error=您不能删除主邮箱。 orgs.org_manage_panel=组织管理 orgs.name=名称 @@ -3098,30 +3255,39 @@ auths.oauth2_required_claim_name_helper=设置此名称,只有具有此名称 auths.oauth2_required_claim_value=必须填写 Claim 声明的值 auths.oauth2_required_claim_value_helper=设置此值,只有拥有对应的声明(Claim)的名称和值的用户才被允许从此源登录 auths.oauth2_group_claim_name=用于提供用户组名称的 Claim 声明名称。(可选) +auths.oauth2_full_name_claim_name=全名声明名称。(可选,如果设置,用户的全名将始终与此声明同步) auths.oauth2_ssh_public_key_claim_name=SSH 公钥声明名称 +auths.oauth2_admin_group=管理员用户组的 Claim 声明值。(可选 — 需要上面的声明名称) +auths.oauth2_restricted_group=受限用户组的 Claim 声明值。(可选 — 需要上面的声明名称) +auths.oauth2_map_group_to_team=映射声明的组到组织团队。(可选 — 要求在上面填写声明的名字) auths.oauth2_map_group_to_team_removal=如果用户不属于相应的组,从已同步团队中移除用户 auths.enable_auto_register=允许用户自动注册 auths.sspi_auto_create_users=自动创建用户 +auths.sspi_auto_create_users_helper=允许 SSPI 认证在用户第一次登录时自动创建新账号 auths.sspi_auto_activate_users=自动激活用户 auths.sspi_auto_activate_users_helper=允许 SSPI 认证自动激活新用户 auths.sspi_strip_domain_names=从用户名中删除域名部分 +auths.sspi_strip_domain_names_helper=如果选中此项,域名将从登录名中删除(例如,「DOMAIN\user」和「user@example.org」,两者都将变成只是「用户」)。 auths.sspi_separator_replacement=要使用的分隔符代替\, / 和 @ +auths.sspi_separator_replacement_helper=用于替换下级登录名称分隔符的字符(例如「DOMAIN\user」)中的 \ 和用户主名字(如「user@example.org」中的 @)。 auths.sspi_default_language=默认语言 +auths.sspi_default_language_helper=通过 SSPI 身份验证方式自动创建的用户的默认语言。如果您希望自动检测语言,请留空。 auths.tips=帮助提示 auths.tips.oauth2.general=OAuth2 认证 auths.tips.oauth2.general.tip=当注册新的 OAuth2 身份验证时,回调/重定向 URL 应该是: auths.tip.oauth2_provider=OAuth2 提供程序 auths.tip.bitbucket=在 %s 注册新的 OAuth 使用者同时添加权限「账号」-「读取」 +auths.tip.nextcloud=使用下面的菜单「设置 -> 安全 -> OAuth 2.0 客户端」在您的实例上注册一个新的 OAuth 客户端 auths.tip.dropbox=在 %s 上创建一个新的应用程序 auths.tip.facebook=在 %s 注册一个新的应用,并添加产品「Facebook 登录」 auths.tip.github=在 %s 注册一个 OAuth 应用程序 auths.tip.gitlab_new=在 %s 注册一个新的应用 auths.tip.google_plus=从谷歌 API 控制台 %s 获得 OAuth2 客户端凭据 -auths.tip.openid_connect=使用 OpenID 连接发现 URL ({server}/.well-known/openid-configuration) 来指定终点 +auths.tip.openid_connect=使用 OpenID 连接发现 URL「{server}/.well-known/openid-configuration」来指定终点 auths.tip.twitter=访问 %s,创建应用并确保启用了「允许此应用程序使用 Twitter 登录」的选项 auths.tip.discord=在 %s 上注册新应用程序 auths.tip.gitea=注册一个新的 OAuth2 应用程序。可以访问 %s 查看帮助 -auths.tip.yandex=在 %s 上创建一个新的应用。在「Yandex.Passport API」这部分中选择以下权限:「访问邮箱地址」,「访问用户头像」和「访问用户名,名字和姓氏,性别」 +auths.tip.yandex=在 %s 上创建一个新的应用。在「Yandex.Passport API」这部分中选择以下权限:「访问邮箱地址」、「访问用户头像」和「访问用户名,名字和姓氏,性别」 auths.tip.mastodon=输入您想要认证的 mastodon 实例的自定义 URL (或使用默认值) auths.edit=修改认证源 auths.activated=该认证源已经启用 @@ -3140,7 +3306,7 @@ auths.invalid_openIdConnectAutoDiscoveryURL=无效的自动发现 URL(这必 config.server_config=服务器配置 config.app_name=站点名称 -config.app_ver=Gitea版本 +config.app_ver=Gitea 版本 config.app_url=Gitea 基本 URL config.custom_conf=配置文件路径 config.custom_file_root_path=自定义文件根路径 @@ -3221,6 +3387,7 @@ config.mailer_sendmail_path=Sendmail 路径 config.mailer_sendmail_args=Sendmail 的额外参数 config.mailer_sendmail_timeout=Sendmail 超时 config.mailer_use_dummy=Dummy +config.test_email_placeholder=电子邮箱(例如,test@example.com) config.send_test_mail=发送测试邮件 config.send_test_mail_submit=发送 config.test_mail_failed=发送测试邮件至「%s」失败:%v @@ -3229,29 +3396,29 @@ config.test_mail_sent=测试邮件已经发送至「%s」。 config.oauth_config=OAuth 配置 config.oauth_enabled=启用 -config.cache_config=Cache 配置 -config.cache_adapter=Cache 适配器 -config.cache_interval=Cache 周期 -config.cache_conn=Cache 连接字符串 +config.cache_config=缓存配置 +config.cache_adapter=缓存适配器 +config.cache_interval=缓存周期 +config.cache_conn=缓存连接字符串 config.cache_item_ttl=缓存项目 TTL config.cache_test=测试缓存 -config.cache_test_failed=缓存测试失败: %v。 +config.cache_test_failed=缓存测试失败:%v。 config.cache_test_slow=缓存测试成功,但响应缓慢:%s。 config.cache_test_succeeded=缓存测试成功,在 %s 时间内得到响应。 -config.session_config=Session 配置 -config.session_provider=Session 提供者 +config.session_config=会话配置 +config.session_provider=会话提供者 config.provider_config=提供者配置 config.cookie_name=Cookie 名称 config.gc_interval_time=GC 周期 -config.session_life_time=Session 生命周期 +config.session_life_time=会话生命周期 config.https_only=仅限 HTTPS config.cookie_life_time=Cookie 生命周期 config.picture_config=图片和头像配置 config.picture_service=图片服务 config.disable_gravatar=禁用 Gravatar 头像 -config.enable_federated_avatar=启用 Federated Avatars +config.enable_federated_avatar=启用 Federated 头像 config.open_with_editor_app_help=用于克隆菜单的编辑器。如果为空将使用默认值。展开可以查看默认值。 config.git_config=Git 配置 @@ -3267,11 +3434,11 @@ config.git_pull_timeout=拉取操作超时 config.git_gc_timeout=GC 操作超时 config.log_config=日志配置 -config.logger_name_fmt=日志:%s +config.logger_name_fmt=%s 日志 config.disabled_logger=禁用 config.access_log_mode=访问日志模式 config.access_log_template=访问日志模板 -config.xorm_log_sql=日志 SQL +config.xorm_log_sql=SQL 日志 config.set_setting_failed=设置 %s 失败 @@ -3294,6 +3461,7 @@ monitor.start=开始时间 monitor.execute_time=执行时长 monitor.last_execution_result=结果 monitor.process.cancel=中止进程 +monitor.process.cancel_desc=中止一个进程可能导致数据丢失 monitor.process.children=子进程 monitor.queues=队列 @@ -3308,6 +3476,7 @@ monitor.queue.numberinqueue=队列中的数量 monitor.queue.review_add=查看 / 添加工作者 monitor.queue.settings.title=池设置 monitor.queue.settings.desc=因为工作者队列阻塞,池正在动态扩展。 +monitor.queue.settings.maxnumberworkers=最大工作者数量 monitor.queue.settings.maxnumberworkers.placeholder=当前 %[1]d monitor.queue.settings.maxnumberworkers.error=最大工作者数必须是数字 monitor.queue.settings.submit=更新设置 @@ -3333,12 +3502,16 @@ notices.delete_success=系统通知已删除。 self_check.no_problem_found=尚未发现问题。 self_check.startup_warnings=启动警告: self_check.database_collation_mismatch=期望数据库使用的校验方式:%s -self_check.location_origin_mismatch=当前 URL(%[1]s)与 Gitea 的 URL(%[2]s)不匹配 。 如果您正在使用反向代理,请确保设置正确的「Host」和「X-Forwarded-Proto」标头。 +self_check.database_collation_case_insensitive=数据库正在使用一个排序规则 %s,这是一个不区分大小写的排序规则。虽然 Gitea 可以在此环境下工作,但可能存在一些无法按预期工作的罕见情况。 +self_check.database_inconsistent_collation_columns=数据库正在使用排序规则 %s,但这些列使用了不匹配的排序规则。这可能会导致一些意外问题。 +self_check.database_fix_mysql=对于 MySQL/MariaDB 用户,您可以使用「gitea doctor convert」命令来解决校验问题。 或者您也可以通过「ALTER ... COLLATE ...」这样的 SQL 来手动解决这个问题。 +self_check.database_fix_mssql=对于 MSSQL 用户,您现在只能通过「ALTER ... COLLATE ...」SQL 手动解决这个问题。 +self_check.location_origin_mismatch=当前 URL(%[1]s)与 Gitea 的 URL(%[2]s)不匹配。如果您正在使用反向代理,请确保设置正确的「Host」和「X-Forwarded-Proto」标头。 [action] create_repo=创建了仓库 %s -rename_repo=重命名仓库 %[1]s 为 %[3]s -commit_repo=推送到了仓库 %[4]s 的 %[3]s 分支 +rename_repo=重命名了仓库 %[1]s 为 %[3]s +commit_repo=推送了仓库 %[4]s 的 %[3]s 分支 create_issue=`创建了工单 %[3]s#%[2]s` close_issue=`关闭了工单 %[3]s#%[2]s` reopen_issue=`重新打开了工单 %[3]s#%[2]s` @@ -3350,9 +3523,9 @@ comment_pull=`评论了合并请求 %[3]s#%[2]s` merge_pull_request=`合并了合并请求 %[3]s#%[2]s` auto_merge_pull_request=`自动合并了合并请求 %[3]s#%[2]s` transfer_repo=将仓库 %s 转移至 %s -push_tag=推送了标签 %[3]s 至仓库 %[4]s -delete_tag=从%[3]s 删除了标签 %[2]s -delete_branch=从 %[3]s 删除分支 %[2]s +push_tag=推送了 Git 标签 %[3]s 至仓库 %[4]s +delete_tag=从 %[3]s 删除了 Git 标签 %[2]s +delete_branch=从 %[3]s 删除了分支 %[2]s compare_branch=比较 compare_commits=比较 %d 提交 compare_commits_general=比较提交 @@ -3360,13 +3533,13 @@ mirror_sync_push=从镜像同步了提交至仓库 %[4]s 的 mirror_sync_create=从镜像同步了引用 %[3]s 至仓库 %[4]s mirror_sync_delete=从镜像同步并从 %[3]s 删除了引用 %[2]s approve_pull_request=`批准了 %[3]s#%[2]s` -reject_pull_request=`建议变更 %[3]s#%[2]s` +reject_pull_request=`建议了变更 %[3]s#%[2]s` publish_release=`在 %[3]s 发布了 %[4]s ` -review_dismissed=`取消了 %[4]s 对 %[3]s#%[2]s 的变更请求` +review_dismissed=`取消了 %[4]s 对 %[3]s#%[2]s 的评审` review_dismissed_reason=原因: create_branch=于 %[4]s 创建了分支 %[3]s starred_repo=点赞了 %[2]s -watched_repo=开始关注 %[2]s +watched_repo=关注了 %[2]s [tool] now=现在 @@ -3389,7 +3562,7 @@ raw_seconds=秒 raw_minutes=分钟 [dropzone] -default_message=拖动文件或者点击此处上传。 +default_message=拖曳文件或点击此处上传。 invalid_input_type=您不能上传该类型的文件 file_too_big=文件体积({{filesize}} MB)超过了最大允许体积({{maxFilesize}} MB) remove_file=移除文件 @@ -3416,6 +3589,8 @@ error.no_committer_account=没有帐户链接到提交者的邮箱 error.no_gpg_keys_found=找不到此签名对应的密钥 error.not_signed_commit=未签名的提交 error.failed_retrieval_gpg_keys=找不到任何与该提交者账号相关的密钥 +error.probable_bad_signature=警告!虽然数据库中有一个此 ID 的密钥,但它没有验证此提交!此提交是可疑的。 +error.probable_bad_default_signature=警告!虽然默认密钥拥有此 ID,但它没有验证此提交!此提交是可疑的。 [units] unit=单元 @@ -3454,6 +3629,7 @@ versions.view_all=查看全部 dependency.id=ID dependency.version=版本 search_in_external_registry=在 %s 中搜索 +alpine.registry=通过在您的 /etc/apk/repositories 文件中添加 URL 来设置此注册中心: alpine.registry.key=下载注册中心公开的 RSA 密钥到 /etc/apk/keys/ 文件夹来验证索引签名: alpine.registry.info=从下面的列表中选择 $branch 和 $repository。 alpine.install=要安装软件包,请运行以下命令: @@ -3466,13 +3642,18 @@ arch.install=使用 pacman 同步软件包: arch.repository=仓库信息 arch.repository.repositories=仓库 arch.repository.architectures=架构 +cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:~/.cargo/config.toml): cargo.install=要使用 Cargo 安装软件包,请运行以下命令: +chef.registry=在您的 ~/.chef/config.rb 文件中设置此注册中心: chef.install=要安装软件包,请运行以下命令: +composer.registry=在您的 ~/.composer/config.json 文件中设置此注册中心: composer.install=要使用 Composer 安装软件包,请运行以下命令: composer.dependencies=依赖 composer.dependencies.development=开发依赖 conan.details.repository=仓库 +conan.registry=从命令行设置此注册中心: conan.install=要使用 Conan 安装软件包,请运行以下命令: +conda.registry=在您的 .condarc 文件中将此注册中心设置为 Conda 仓库: conda.install=要使用 Conda 安装软件包,请运行以下命令: container.details.type=镜像类型 container.details.platform=平台 @@ -3484,7 +3665,9 @@ container.layers=镜像层 container.labels=标签 container.labels.key=键 container.labels.value=值 +cran.registry=在您的 Rprofile.site 文件中设置此注册中心: cran.install=要安装软件包,请运行以下命令: +debian.registry=从命令行设置此注册中心: debian.registry.info=从下面的列表中选择 $distribution 和 $component。 debian.install=要安装软件包,请运行以下命令: debian.repository=仓库信息 @@ -3493,11 +3676,16 @@ debian.repository.components=组件 debian.repository.architectures=架构 generic.download=从命令行下载软件包: go.install=通过命令行安装软件包: +helm.registry=从命令行设置此注册中心: helm.install=要安装包,请运行以下命令: +maven.registry=在您项目的 pom.xml 文件中设置此注册中心: +maven.install=要使用这个软件包,在 pom.xml 文件中的 依赖项 块中包含以下内容: maven.install2=通过命令行运行: maven.download=要下载依赖项,请通过命令行运行: +nuget.registry=从命令行设置此注册中心: nuget.install=要使用 Nuget 安装软件包,请运行以下命令: nuget.dependency.framework=目标框架 +npm.registry=在您项目的 .npmrc 文件中设置此注册中心: npm.install=要使用 npm 安装软件包,请运行以下命令: npm.install2=或将其添加到 package.json 文件: npm.dependencies=依赖项 @@ -3509,6 +3697,7 @@ npm.details.tag=标签 pub.install=要使用 Dart 安装软件包,请运行以下命令: pypi.requires=需要 Python pypi.install=要使用 pip 安装软件包,请运行以下命令: +rpm.registry=从命令行设置此仓库: rpm.distros.redhat=在基于 RedHat 的发行版 rpm.distros.suse=在基于 SUSE 的发行版 rpm.install=要安装软件包,请运行以下命令: @@ -3521,7 +3710,8 @@ rubygems.dependencies.runtime=运行时依赖 rubygems.dependencies.development=开发依赖 rubygems.required.ruby=需要 Ruby 版本 rubygems.required.rubygems=需要 RubyGem 版本 -swift.install=在您的 Package.swift文件中添加该包: +swift.registry=从命令行设置此仓库: +swift.install=在您的 Package.swift 文件中添加该包: swift.install2=并运行以下命令: vagrant.install=若要添加一个 Vagrant box,请运行以下命令: settings.link=将此软件包链接到仓库 @@ -3538,7 +3728,7 @@ settings.delete.error=删除软件包失败。 owner.settings.cargo.title=Cargo 注册中心索引 owner.settings.cargo.initialize=初始化索引 owner.settings.cargo.initialize.description=使用 Cargo 注册中心时需要一个特殊索引的 Git 仓库。使用此选项将(重新)创建仓库并自动配置它。 -owner.settings.cargo.initialize.error=初始化 Cargo 索引失败: %v +owner.settings.cargo.initialize.error=初始化 Cargo 索引失败:%v owner.settings.cargo.initialize.success=Cargo 索引已经成功创建。 owner.settings.cargo.rebuild=重建索引 owner.settings.cargo.rebuild.description=如果索引与存储的 Cargo 包不同步,重建可能会有用。 @@ -3631,6 +3821,7 @@ runners.delete_runner=删除此运行器 runners.delete_runner_success=运行器删除成功 runners.delete_runner_failed=运行器删除失败 runners.delete_runner_header=确认要删除此运行器 +runners.delete_runner_notice=如果一个任务正在运行在此运行器上,它将被终止并标记为失败。它可能会打断正在构建的工作流。 runners.none=无可用运行器 runners.status.unspecified=未知 runners.status.idle=空闲 diff --git a/package-lock.json b/package-lock.json index 21e29a2081d..ecf333c9a62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@github/relative-time-element": "4.4.8", "@github/text-expander-element": "2.9.2", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", - "@primer/octicons": "19.15.3", + "@primer/octicons": "19.15.5", "@silverwind/vue3-calendar-heatmap": "2.0.6", "add-asset-webpack-plugin": "3.0.0", "ansi_up": "6.0.6", @@ -34,7 +34,7 @@ "jquery": "3.7.1", "katex": "0.16.22", "license-checker-webpack-plugin": "0.2.1", - "mermaid": "11.8.0", + "mermaid": "11.10.0", "mini-css-extract-plugin": "2.9.2", "minimatch": "10.0.3", "monaco-editor": "0.52.2", @@ -46,7 +46,7 @@ "postcss-loader": "8.1.1", "postcss-nesting": "13.0.2", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.26.0", + "swagger-ui-dist": "5.27.0", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", @@ -56,20 +56,20 @@ "typescript": "5.8.3", "uint8-to-base64": "0.2.1", "vanilla-colorful": "0.7.2", - "vue": "3.5.17", + "vue": "3.5.18", "vue-bar-graph": "2.2.0", "vue-chartjs": "5.3.2", "vue-loader": "17.4.2", - "webpack": "5.99.9", + "webpack": "5.101.0", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.0" }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.53.2", + "@playwright/test": "1.54.1", "@stoplight/spectral-cli": "6.15.0", "@stylistic/eslint-plugin-js": "3.1.0", - "@stylistic/stylelint-plugin": "3.1.3", + "@stylistic/stylelint-plugin": "4.0.0", "@types/dropzone": "5.7.9", "@types/jquery": "3.5.32", "@types/katex": "0.16.7", @@ -80,9 +80,9 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/eslint-plugin": "8.35.1", - "@typescript-eslint/parser": "8.35.1", - "@vitejs/plugin-vue": "6.0.0", + "@typescript-eslint/eslint-plugin": "8.38.0", + "@typescript-eslint/parser": "8.38.0", + "@vitejs/plugin-vue": "6.0.1", "@vitest/eslint-plugin": "1.3.4", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.4.4", @@ -91,11 +91,11 @@ "eslint-plugin-import-x": "4.16.1", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", - "eslint-plugin-playwright": "2.2.0", + "eslint-plugin-playwright": "2.2.2", "eslint-plugin-regexp": "2.9.0", "eslint-plugin-sonarjs": "3.0.4", "eslint-plugin-unicorn": "56.0.1", - "eslint-plugin-vue": "10.3.0", + "eslint-plugin-vue": "10.4.0", "eslint-plugin-vue-scoped-css": "2.11.0", "eslint-plugin-wc": "3.0.1", "happy-dom": "18.0.1", @@ -103,18 +103,18 @@ "material-icon-theme": "5.24.0", "nolyfill": "1.0.44", "postcss-html": "1.8.0", - "stylelint": "16.21.1", - "stylelint-config-recommended": "16.0.0", + "stylelint": "16.23.1", + "stylelint-config-recommended": "17.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", - "stylelint-define-config": "16.21.0", + "stylelint-define-config": "16.22.0", "stylelint-value-no-unknown-custom-properties": "6.0.1", "svgo": "4.0.0", "type-fest": "4.41.0", - "updates": "16.4.2", - "vite-string-plugin": "1.4.4", + "updates": "16.5.2", + "vite-string-plugin": "1.4.6", "vitest": "3.2.4", - "vue-tsc": "3.0.1" + "vue-tsc": "3.0.4" }, "engines": { "node": ">= 20.0.0" @@ -218,18 +218,18 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", + "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -474,9 +474,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", - "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", "dev": true, "funding": [ { @@ -493,8 +493,52 @@ "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@csstools/css-tokenizer": "^3.0.1" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/selector-resolve-nested": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", + "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" } }, "node_modules/@discoveryjs/json-ext": { @@ -518,21 +562,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", - "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.0.2", + "@emnapi/wasi-threads": "1.0.4", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", - "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", "dev": true, "license": "MIT", "optional": true, @@ -541,9 +585,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", - "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", "dev": true, "license": "MIT", "optional": true, @@ -552,9 +596,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", + "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", "cpu": [ "ppc64" ], @@ -568,9 +612,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", + "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", "cpu": [ "arm" ], @@ -584,9 +628,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", + "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", "cpu": [ "arm64" ], @@ -600,9 +644,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", + "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", "cpu": [ "x64" ], @@ -616,9 +660,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", + "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", "cpu": [ "arm64" ], @@ -632,9 +676,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", + "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", "cpu": [ "x64" ], @@ -648,9 +692,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", + "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", "cpu": [ "arm64" ], @@ -664,9 +708,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", + "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", "cpu": [ "x64" ], @@ -680,9 +724,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", + "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", "cpu": [ "arm" ], @@ -696,9 +740,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", + "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", "cpu": [ "arm64" ], @@ -712,9 +756,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", + "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", "cpu": [ "ia32" ], @@ -728,9 +772,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", + "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", "cpu": [ "loong64" ], @@ -744,9 +788,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", + "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", "cpu": [ "mips64el" ], @@ -760,9 +804,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", + "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", "cpu": [ "ppc64" ], @@ -776,9 +820,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", + "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", "cpu": [ "riscv64" ], @@ -792,9 +836,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", + "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", "cpu": [ "s390x" ], @@ -808,9 +852,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", + "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", "cpu": [ "x64" ], @@ -824,9 +868,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", + "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", "cpu": [ "arm64" ], @@ -840,9 +884,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", + "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", "cpu": [ "x64" ], @@ -856,9 +900,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", + "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", "cpu": [ "arm64" ], @@ -872,9 +916,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", + "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", "cpu": [ "x64" ], @@ -887,10 +931,26 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", + "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", + "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", "cpu": [ "x64" ], @@ -904,9 +964,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", + "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", "cpu": [ "arm64" ], @@ -920,9 +980,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", + "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", "cpu": [ "ia32" ], @@ -936,9 +996,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", + "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", "cpu": [ "x64" ], @@ -1431,39 +1491,11 @@ } }, "node_modules/@keyv/serialize": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", - "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.0.tgz", + "integrity": "sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==", "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^6.0.3" - } - }, - "node_modules/@keyv/serialize/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } + "license": "MIT" }, "node_modules/@kurkle/color": { "version": "0.3.4", @@ -1523,25 +1555,25 @@ } }, "node_modules/@mermaid-js/parser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.0.tgz", - "integrity": "sha512-7DNESgpyZ5WG1SIkrYafVBhWmImtmQuoxOO1lawI3gQYWxBX3v1FW3IyuuRfKJAO06XrZR71W0Kif5VEGGd4VA==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.2.tgz", + "integrity": "sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ==", "license": "MIT", "dependencies": { "langium": "3.3.1" } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", - "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.9.0" + "@tybys/wasm-util": "^0.10.0" } }, "node_modules/@nodelib/fs.scandir": { @@ -1597,9 +1629,9 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", - "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, "license": "MIT", "engines": { @@ -1610,13 +1642,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.54.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.1.tgz", + "integrity": "sha512-FS8hQ12acieG2dYSksmLOF7BNxnVf2afRJdCuM1eMSxj6QTSE6G4InGF7oApGgDb65MX7AwMVlIkpru0yZA4Xw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.53.2" + "playwright": "1.54.1" }, "bin": { "playwright": "cli.js" @@ -1636,18 +1668,18 @@ } }, "node_modules/@primer/octicons": { - "version": "19.15.3", - "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-19.15.3.tgz", - "integrity": "sha512-SVD0JbTzabLqLx4d5Cl3cyY+i0u3j5/lI6P3FyNkkJb9Z4VAQ+mBvl7WgK0ZFEXBsLc2gxnoYXvC3TkNSEz1NQ==", + "version": "19.15.5", + "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-19.15.5.tgz", + "integrity": "sha512-FCXPTlXlHvAS3rRBd1C/xVBYSYzPPwS8tNcUxnvUYK6L4/d+zUy2KExLtzW+L9xKo2z8J9uY+c1VCsNRf+b4MQ==", "license": "MIT", "dependencies": { "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==", + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", + "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", "dev": true, "license": "MIT" }, @@ -1699,9 +1731,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.2.tgz", - "integrity": "sha512-g0dF8P1e2QYPOj1gu7s/3LVP6kze9A7m6x0BZ9iTdXK8N5c2V7cpBKHV3/9A4Zd8xxavdhK0t4PnqjkqVmUc9Q==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", + "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", "cpu": [ "arm" ], @@ -1713,9 +1745,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.2.tgz", - "integrity": "sha512-Yt5MKrOosSbSaAK5Y4J+vSiID57sOvpBNBR6K7xAaQvk3MkcNVV0f9fE20T+41WYN8hDn6SGFlFrKudtx4EoxA==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", + "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", "cpu": [ "arm64" ], @@ -1727,9 +1759,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.2.tgz", - "integrity": "sha512-EsnFot9ZieM35YNA26nhbLTJBHD0jTwWpPwmRVDzjylQT6gkar+zenfb8mHxWpRrbn+WytRRjE0WKsfaxBkVUA==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", + "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", "cpu": [ "arm64" ], @@ -1741,9 +1773,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.2.tgz", - "integrity": "sha512-dv/t1t1RkCvJdWWxQ2lWOO+b7cMsVw5YFaS04oHpZRWehI1h0fV1gF4wgGCTyQHHjJDfbNpwOi6PXEafRBBezw==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", + "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", "cpu": [ "x64" ], @@ -1755,9 +1787,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.2.tgz", - "integrity": "sha512-W4tt4BLorKND4qeHElxDoim0+BsprFTwb+vriVQnFFtT/P6v/xO5I99xvYnVzKWrK6j7Hb0yp3x7V5LUbaeOMg==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", + "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", "cpu": [ "arm64" ], @@ -1769,9 +1801,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.2.tgz", - "integrity": "sha512-tdT1PHopokkuBVyHjvYehnIe20fxibxFCEhQP/96MDSOcyjM/shlTkZZLOufV3qO6/FQOSiJTBebhVc12JyPTA==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", + "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", "cpu": [ "x64" ], @@ -1783,9 +1815,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.2.tgz", - "integrity": "sha512-+xmiDGGaSfIIOXMzkhJ++Oa0Gwvl9oXUeIiwarsdRXSe27HUIvjbSIpPxvnNsRebsNdUo7uAiQVgBD1hVriwSQ==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", + "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", "cpu": [ "arm" ], @@ -1797,9 +1829,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.2.tgz", - "integrity": "sha512-bDHvhzOfORk3wt8yxIra8N4k/N0MnKInCW5OGZaeDYa/hMrdPaJzo7CSkjKZqX4JFUWjUGm88lI6QJLCM7lDrA==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", + "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", "cpu": [ "arm" ], @@ -1811,9 +1843,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.2.tgz", - "integrity": "sha512-NMsDEsDiYghTbeZWEGnNi4F0hSbGnsuOG+VnNvxkKg0IGDvFh7UVpM/14mnMwxRxUf9AdAVJgHPvKXf6FpMB7A==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", + "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", "cpu": [ "arm64" ], @@ -1825,9 +1857,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.2.tgz", - "integrity": "sha512-lb5bxXnxXglVq+7imxykIp5xMq+idehfl+wOgiiix0191av84OqbjUED+PRC5OA8eFJYj5xAGcpAZ0pF2MnW+A==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", + "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", "cpu": [ "arm64" ], @@ -1839,9 +1871,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.2.tgz", - "integrity": "sha512-Yl5Rdpf9pIc4GW1PmkUGHdMtbx0fBLE1//SxDmuf3X0dUC57+zMepow2LK0V21661cjXdTn8hO2tXDdAWAqE5g==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", + "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", "cpu": [ "loong64" ], @@ -1852,10 +1884,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.2.tgz", - "integrity": "sha512-03vUDH+w55s680YYryyr78jsO1RWU9ocRMaeV2vMniJJW/6HhoTBwyyiiTPVHNWLnhsnwcQ0oH3S9JSBEKuyqw==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", + "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", "cpu": [ "ppc64" ], @@ -1867,9 +1899,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.2.tgz", - "integrity": "sha512-iYtAqBg5eEMG4dEfVlkqo05xMOk6y/JXIToRca2bAWuqjrJYJlx/I7+Z+4hSrsWU8GdJDFPL4ktV3dy4yBSrzg==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", + "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", "cpu": [ "riscv64" ], @@ -1881,9 +1913,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.2.tgz", - "integrity": "sha512-e6vEbgaaqz2yEHqtkPXa28fFuBGmUJ0N2dOJK8YUfijejInt9gfCSA7YDdJ4nYlv67JfP3+PSWFX4IVw/xRIPg==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", + "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", "cpu": [ "riscv64" ], @@ -1895,9 +1927,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.2.tgz", - "integrity": "sha512-evFOtkmVdY3udE+0QKrV5wBx7bKI0iHz5yEVx5WqDJkxp9YQefy4Mpx3RajIVcM6o7jxTvVd/qpC1IXUhGc1Mw==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", + "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", "cpu": [ "s390x" ], @@ -1909,9 +1941,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.2.tgz", - "integrity": "sha512-/bXb0bEsWMyEkIsUL2Yt5nFB5naLAwyOWMEviQfQY1x3l5WsLKgvZf66TM7UTfED6erckUVUJQ/jJ1FSpm3pRQ==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", + "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", "cpu": [ "x64" ], @@ -1923,9 +1955,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.2.tgz", - "integrity": "sha512-3D3OB1vSSBXmkGEZR27uiMRNiwN08/RVAcBKwhUYPaiZ8bcvdeEwWPvbnXvvXHY+A/7xluzcN+kaiOFNiOZwWg==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", + "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", "cpu": [ "x64" ], @@ -1937,9 +1969,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.2.tgz", - "integrity": "sha512-VfU0fsMK+rwdK8mwODqYeM2hDrF2WiHaSmCBrS7gColkQft95/8tphyzv2EupVxn3iE0FI78wzffoULH1G+dkw==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", + "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", "cpu": [ "arm64" ], @@ -1951,9 +1983,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.2.tgz", - "integrity": "sha512-+qMUrkbUurpE6DVRjiJCNGZBGo9xM4Y0FXU5cjgudWqIBWbcLkjE3XprJUsOFgC6xjBClwVa9k6O3A7K3vxb5Q==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", + "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", "cpu": [ "ia32" ], @@ -1965,9 +1997,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.2.tgz", - "integrity": "sha512-3+QZROYfJ25PDcxFF66UEk8jGWigHJeecZILvkPkyQN7oc5BvFo4YEXFkOs154j3FTMp9mn9Ky8RCOwastduEA==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", + "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", "cpu": [ "x64" ], @@ -2540,18 +2572,17 @@ } }, "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": "4.0.0", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-4.0.0.tgz", + "integrity": "sha512-CFwt3K4Y/7bygNCLCQ8Sy4Hzgbhxq3BsNW0FIuYxl17HD3ywptm54ocyeiLVRrk5jtz1Zwks7Xr9eiZt8SWHAw==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@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", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3", + "postcss": "^8.5.6", + "postcss-selector-parser": "^7.1.0", "postcss-value-parser": "^4.2.0", "style-search": "^0.1.0" }, @@ -2559,7 +2590,7 @@ "node": "^18.12 || >=20.9" }, "peerDependencies": { - "stylelint": "^16.8.0" + "stylelint": "^16.22.0" } }, "node_modules/@swc/helpers": { @@ -2569,9 +2600,9 @@ "license": "MIT" }, "node_modules/@tybys/wasm-util": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", - "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", "dev": true, "license": "MIT", "optional": true, @@ -2689,9 +2720,9 @@ "license": "MIT" }, "node_modules/@types/d3-dispatch": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", - "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", "license": "MIT" }, "node_modules/@types/d3-drag": { @@ -2987,9 +3018,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.10.tgz", - "integrity": "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", + "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", "license": "MIT", "dependencies": { "undici-types": "~7.8.0" @@ -3140,13 +3171,13 @@ } }, "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">= 12" } }, "node_modules/@types/whatwg-mimetype": { @@ -3157,17 +3188,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.1.tgz", - "integrity": "sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz", + "integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.35.1", - "@typescript-eslint/type-utils": "8.35.1", - "@typescript-eslint/utils": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/type-utils": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -3181,7 +3212,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.35.1", + "@typescript-eslint/parser": "^8.38.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -3197,16 +3228,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.35.1.tgz", - "integrity": "sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz", + "integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.35.1", - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/typescript-estree": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", "debug": "^4.3.4" }, "engines": { @@ -3222,14 +3253,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.35.1.tgz", - "integrity": "sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", + "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.35.1", - "@typescript-eslint/types": "^8.35.1", + "@typescript-eslint/tsconfig-utils": "^8.38.0", + "@typescript-eslint/types": "^8.38.0", "debug": "^4.3.4" }, "engines": { @@ -3244,14 +3275,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.35.1.tgz", - "integrity": "sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", + "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1" + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3262,9 +3293,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.1.tgz", - "integrity": "sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", + "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", "dev": true, "license": "MIT", "engines": { @@ -3279,14 +3310,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.35.1.tgz", - "integrity": "sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", + "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.35.1", - "@typescript-eslint/utils": "8.35.1", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3303,9 +3335,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.35.1.tgz", - "integrity": "sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", "dev": true, "license": "MIT", "engines": { @@ -3317,16 +3349,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.1.tgz", - "integrity": "sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", + "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.35.1", - "@typescript-eslint/tsconfig-utils": "8.35.1", - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1", + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3379,16 +3411,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.35.1.tgz", - "integrity": "sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", + "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.35.1", - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/typescript-estree": "8.35.1" + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3403,13 +3435,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.35.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.1.tgz", - "integrity": "sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw==", + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", + "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.1", + "@typescript-eslint/types": "8.38.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3428,9 +3460,9 @@ "license": "ISC" }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.10.1.tgz", - "integrity": "sha512-zohDKXT1Ok0yhbVGff4YAg9HUs5ietG5GpvJBPFSApZnGe7uf2cd26DRhKZbn0Be6xHUZrSzP+RAgMmzyc71EA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", "cpu": [ "arm" ], @@ -3442,9 +3474,9 @@ ] }, "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.10.1.tgz", - "integrity": "sha512-tAN6k5UrTd4nicpA7s2PbjR/jagpDzAmvXFjbpTazUe5FRsFxVcBlS1F5Lzp5jtWU6bdiqRhSvd4X8rdpCffeA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", "cpu": [ "arm64" ], @@ -3456,9 +3488,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.10.1.tgz", - "integrity": "sha512-+FCsag8WkauI4dQ50XumCXdfvDCZEpMUnvZDsKMxfOisnEklpDFXc6ThY0WqybBYZbiwR5tWcFaZmI0G6b4vrg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", "cpu": [ "arm64" ], @@ -3470,9 +3502,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.10.1.tgz", - "integrity": "sha512-qYKGGm5wk71ONcXTMZ0+J11qQeOAPz3nw6VtqrBUUELRyXFyvK8cHhHsLBFR4GHnilc2pgY1HTB2TvdW9wO26Q==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", "cpu": [ "x64" ], @@ -3484,9 +3516,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.10.1.tgz", - "integrity": "sha512-hOHMAhbvIQ63gkpgeNsXcWPSyvXH7ZEyeg254hY0Lp/hX8NdW+FsUWq73g9946Pc/BrcVI/I3C1cmZ4RCX9bNw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", "cpu": [ "x64" ], @@ -3498,9 +3530,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.10.1.tgz", - "integrity": "sha512-6ds7+zzHJgTDmpe0gmFcOTvSUhG5oZukkt+cCsSb3k4Uiz2yEQB4iCRITX2hBwSW+p8gAieAfecITjgqCkswXw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", "cpu": [ "arm" ], @@ -3512,9 +3544,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.10.1.tgz", - "integrity": "sha512-P7A0G2/jW00diNJyFeq4W9/nxovD62Ay8CMP4UK9OymC7qO7rG1a8Upad68/bdfpIOn7KSp7Aj/6lEW3yyznAA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", "cpu": [ "arm" ], @@ -3526,9 +3558,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.10.1.tgz", - "integrity": "sha512-Cg6xzdkrpltcTPO4At+A79zkC7gPDQIgosJmVV8M104ImB6KZi1MrNXgDYIAfkhUYjPzjNooEDFRAwwPadS7ZA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", "cpu": [ "arm64" ], @@ -3540,9 +3572,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.10.1.tgz", - "integrity": "sha512-aNeg99bVkXa4lt+oZbjNRPC8ZpjJTKxijg/wILrJdzNyAymO2UC/HUK1UfDjt6T7U5p/mK24T3CYOi3/+YEQSA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", "cpu": [ "arm64" ], @@ -3554,9 +3586,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.10.1.tgz", - "integrity": "sha512-ylz5ojeXrkPrtnzVhpCO+YegG63/aKhkoTlY8PfMfBfLaUG8v6m6iqrL7sBUKdVBgOB4kSTUPt9efQdA/Y3Z/w==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", "cpu": [ "ppc64" ], @@ -3568,9 +3600,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.10.1.tgz", - "integrity": "sha512-xcWyhmJfXXOxK7lvE4+rLwBq+on83svlc0AIypfe6x4sMJR+S4oD7n9OynaQShfj2SufPw2KJAotnsNb+4nN2g==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", "cpu": [ "riscv64" ], @@ -3582,9 +3614,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.10.1.tgz", - "integrity": "sha512-mW9JZAdOCyorgi1eLJr4gX7xS67WNG9XNPYj5P8VuttK72XNsmdw9yhOO4tDANMgiLXFiSFaiL1gEpoNtRPw/A==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", "cpu": [ "riscv64" ], @@ -3596,9 +3628,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.10.1.tgz", - "integrity": "sha512-NZGKhBy6xkJ0k09cWNZz4DnhBcGlhDd3W+j7EYoNvf5TSwj2K6kbmfqTWITEgkvjsMUjm1wsrc4IJaH6VtjyHQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", "cpu": [ "s390x" ], @@ -3610,9 +3642,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.10.1.tgz", - "integrity": "sha512-VsjgckJ0gNMw7p0d8In6uPYr+s0p16yrT2rvG4v2jUpEMYkpnfnCiALa9SWshbvlGjKQ98Q2x19agm3iFk8w8Q==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", "cpu": [ "x64" ], @@ -3624,9 +3656,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.10.1.tgz", - "integrity": "sha512-idMnajMeejnaFi0Mx9UTLSYFDAOTfAEP7VjXNgxKApso3Eu2Njs0p2V95nNIyFi4oQVGFmIuCkoznAXtF/Zbmw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", "cpu": [ "x64" ], @@ -3638,9 +3670,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.10.1.tgz", - "integrity": "sha512-7jyhjIRNFjzlr8x5pth6Oi9hv3a7ubcVYm2GBFinkBQKcFhw4nIs5BtauSNtDW1dPIGrxF0ciynCZqzxMrYMsg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", "cpu": [ "wasm32" ], @@ -3655,9 +3687,9 @@ } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.10.1.tgz", - "integrity": "sha512-TY79+N+Gkoo7E99K+zmsKNeiuNJYlclZJtKqsHSls8We2iGhgxtletVsiBYie93MSTDRDMI8pkBZJlIJSZPrdA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", "cpu": [ "arm64" ], @@ -3669,9 +3701,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.10.1.tgz", - "integrity": "sha512-BAJN5PEPlEV+1m8+PCtFoKm3LQ1P57B4Z+0+efU0NzmCaGk7pUaOxuPgl+m3eufVeeNBKiPDltG0sSB9qEfCxw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", "cpu": [ "ia32" ], @@ -3683,9 +3715,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.10.1.tgz", - "integrity": "sha512-2v3erKKmmCyIVvvhI2nF15qEbdBpISTq44m9pyd5gfIJB1PN94oePTLWEd82XUbIbvKhv76xTSeUQSCOGesLeg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", "cpu": [ "x64" ], @@ -3697,13 +3729,13 @@ ] }, "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": "6.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", + "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.19" + "@rolldown/pluginutils": "1.0.0-beta.29" }, "engines": { "node": "^20.19.0 || >=22.12.0" @@ -3889,68 +3921,68 @@ } }, "node_modules/@volar/language-core": { - "version": "2.4.17", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.17.tgz", - "integrity": "sha512-chmRZMbKmcGpKMoO7Reb70uiLrzo0KWC2CkFttKUuKvrE+VYgi+fL9vWMJ07Fv5ulX0V1TAyyacN9q3nc5/ecA==", + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.20.tgz", + "integrity": "sha512-dRDF1G33xaAIDqR6+mXUIjXYdu9vzSxlMGfMEwBxQsfY/JMUEXSpLTR057oTKlUQ2nIvCmP9k94A8h8z2VrNSA==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "2.4.17" + "@volar/source-map": "2.4.20" } }, "node_modules/@volar/source-map": { - "version": "2.4.17", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.17.tgz", - "integrity": "sha512-QDybtQyO3Ms/NjFqNHTC5tbDN2oK5VH7ZaKrcubtfHBDj63n2pizHC3wlMQ+iT55kQXZUUAbmBX5L1C8CHFeBw==", + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.20.tgz", + "integrity": "sha512-mVjmFQH8mC+nUaVwmbxoYUy8cww+abaO8dWzqPUjilsavjxH0jCJ3Mp8HFuHsdewZs2c+SP+EO7hCd8Z92whJg==", "dev": true, "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "2.4.17", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.17.tgz", - "integrity": "sha512-3paEFNh4P5DkgNUB2YkTRrfUekN4brAXxd3Ow1syMqdIPtCZHbUy4AW99S5RO/7mzyTWPMdDSo3mqTpB/LPObQ==", + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.20.tgz", + "integrity": "sha512-Oc4DczPwQyXcVbd+5RsNEqX6ia0+w3p+klwdZQ6ZKhFjWoBP9PCPQYlKYRi/tDemWphW93P/Vv13vcE9I9D2GQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.17", + "@volar/language-core": "2.4.20", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "node_modules/@vue/compiler-core": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz", - "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.18.tgz", + "integrity": "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@vue/shared": "3.5.17", + "@babel/parser": "^7.28.0", + "@vue/shared": "3.5.18", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", - "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz", + "integrity": "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.17", - "@vue/shared": "3.5.17" + "@vue/compiler-core": "3.5.18", + "@vue/shared": "3.5.18" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", - "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz", + "integrity": "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@vue/compiler-core": "3.5.17", - "@vue/compiler-dom": "3.5.17", - "@vue/compiler-ssr": "3.5.17", - "@vue/shared": "3.5.17", + "@babel/parser": "^7.28.0", + "@vue/compiler-core": "3.5.18", + "@vue/compiler-dom": "3.5.18", + "@vue/compiler-ssr": "3.5.18", + "@vue/shared": "3.5.18", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.6", @@ -3967,13 +3999,13 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", - "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz", + "integrity": "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.17", - "@vue/shared": "3.5.17" + "@vue/compiler-dom": "3.5.18", + "@vue/shared": "3.5.18" } }, "node_modules/@vue/compiler-vue2": { @@ -3988,20 +4020,20 @@ } }, "node_modules/@vue/language-core": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.0.1.tgz", - "integrity": "sha512-sq+/Mc1IqIexWEQ+Q2XPiDb5SxSvY5JPqHnMOl/PlF5BekslzduX8dglSkpC17VeiAQB6dpS+4aiwNLJRduCNw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.0.4.tgz", + "integrity": "sha512-BvueED4LfBCSNH66eeUQk37MQCb7hjdezzGgxniM0LbriW53AJIyLorgshAtStmjfsAuOCcTl/c1b+nz/ye8xQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.17", + "@volar/language-core": "2.4.20", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^2.0.5", - "minimatch": "^10.0.1", "muggle-string": "^0.4.1", - "path-browserify": "^1.0.1" + "path-browserify": "^1.0.1", + "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": "*" @@ -4012,54 +4044,67 @@ } } }, + "node_modules/@vue/language-core/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@vue/reactivity": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.17.tgz", - "integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.18.tgz", + "integrity": "sha512-x0vPO5Imw+3sChLM5Y+B6G1zPjwdOri9e8V21NnTnlEvkxatHEH5B5KEAJcjuzQ7BsjGrKtfzuQ5eQwXh8HXBg==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.17" + "@vue/shared": "3.5.18" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.17.tgz", - "integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.18.tgz", + "integrity": "sha512-DUpHa1HpeOQEt6+3nheUfqVXRog2kivkXHUhoqJiKR33SO4x+a5uNOMkV487WPerQkL0vUuRvq/7JhRgLW3S+w==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.17", - "@vue/shared": "3.5.17" + "@vue/reactivity": "3.5.18", + "@vue/shared": "3.5.18" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz", - "integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.18.tgz", + "integrity": "sha512-YwDj71iV05j4RnzZnZtGaXwPoUWeRsqinblgVJwR8XTXYZ9D5PbahHQgsbmzUvCWNF6x7siQ89HgnX5eWkr3mw==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.17", - "@vue/runtime-core": "3.5.17", - "@vue/shared": "3.5.17", + "@vue/reactivity": "3.5.18", + "@vue/runtime-core": "3.5.18", + "@vue/shared": "3.5.18", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.17.tgz", - "integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.18.tgz", + "integrity": "sha512-PvIHLUoWgSbDG7zLHqSqaCoZvHi6NNmfVFOqO+OnwvqMz/tqQr3FuGWS8ufluNddk7ZLBJYMrjcw1c6XzR12mA==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.17", - "@vue/shared": "3.5.17" + "@vue/compiler-ssr": "3.5.18", + "@vue/shared": "3.5.18" }, "peerDependencies": { - "vue": "3.5.17" + "vue": "3.5.18" } }, "node_modules/@vue/shared": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz", - "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.18.tgz", + "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==", "license": "MIT" }, "node_modules/@webassemblyjs/ast": { @@ -4289,6 +4334,18 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -4829,24 +4886,24 @@ } }, "node_modules/cacheable": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.1.tgz", - "integrity": "sha512-Fa2BZY0CS9F0PFc/6aVA6tgpOdw+hmv9dkZOlHXII5v5Hw+meJBIWDcPrG9q/dXxGcNbym5t77fzmawrBQfTmQ==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.3.tgz", + "integrity": "sha512-M6p10iJ/VT0wT7TLIGUnm958oVrU2cUK8pQAVU21Zu7h8rbk/PeRtRWrvHJBql97Bhzk3g1N6+2VKC+Rjxna9Q==", "dev": true, "license": "MIT", "dependencies": { "hookified": "^1.10.0", - "keyv": "^5.3.4" + "keyv": "^5.4.0" } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.4.tgz", - "integrity": "sha512-ypEvQvInNpUe+u+w8BIcPkQvEqXquyyibWE/1NB5T2BTzIpS5cGEV1LZskDzPSTvNAaT4+5FutvzlvnkxOSKlw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.4.0.tgz", + "integrity": "sha512-TMckyVjEoacG5IteUpUrOBsFORtheqziVyyY2dLUwg1jwTb8u48LX4TgmtogkNl9Y9unaEJ1luj10fGyjMGFOQ==", "dev": true, "license": "MIT", "dependencies": { - "@keyv/serialize": "^1.0.3" + "@keyv/serialize": "^1.1.0" } }, "node_modules/callsites": { @@ -4868,9 +4925,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.30001731", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", + "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", "funding": [ { "type": "opencollective", @@ -4888,9 +4945,9 @@ "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz", + "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==", "dev": true, "license": "MIT", "dependencies": { @@ -4901,7 +4958,7 @@ "pathval": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/chalk": { @@ -5080,9 +5137,9 @@ } }, "node_modules/ci-info": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", - "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, "funding": [ { @@ -5282,13 +5339,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.43.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", - "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", + "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.25.0" + "browserslist": "^4.25.1" }, "funding": { "type": "opencollective", @@ -5506,9 +5563,9 @@ "license": "MIT" }, "node_modules/cytoscape": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.0.tgz", - "integrity": "sha512-5JHBC9n75kz5851jeklCPmZWcg3hUe6sjqJvyk3+hVqFaKcHwHgxsjeN1yLmggoUc6STbtm9/NQyabQehfjvWQ==", + "version": "3.33.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.0.tgz", + "integrity": "sha512-2d2EwwhaxLWC8ahkH1PpQwCyu6EY3xDRdcEJXrLTb4fOUtVc+YWQalHU67rFS1a6ngj1fgv9dQLtJxP/KAFZEw==", "license": "MIT", "engines": { "node": ">=0.10" @@ -6323,9 +6380,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.179", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", - "integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==", + "version": "1.5.194", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.194.tgz", + "integrity": "sha512-SdnWJwSUot04UR51I2oPD8kuP2VI37/CADR1OHsFOUzZIvfWJBO6q11k5P/uKNyTT3cdOsnyjkrZ+DDShqYqJA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -6419,9 +6476,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", + "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -6431,31 +6488,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "@esbuild/aix-ppc64": "0.25.8", + "@esbuild/android-arm": "0.25.8", + "@esbuild/android-arm64": "0.25.8", + "@esbuild/android-x64": "0.25.8", + "@esbuild/darwin-arm64": "0.25.8", + "@esbuild/darwin-x64": "0.25.8", + "@esbuild/freebsd-arm64": "0.25.8", + "@esbuild/freebsd-x64": "0.25.8", + "@esbuild/linux-arm": "0.25.8", + "@esbuild/linux-arm64": "0.25.8", + "@esbuild/linux-ia32": "0.25.8", + "@esbuild/linux-loong64": "0.25.8", + "@esbuild/linux-mips64el": "0.25.8", + "@esbuild/linux-ppc64": "0.25.8", + "@esbuild/linux-riscv64": "0.25.8", + "@esbuild/linux-s390x": "0.25.8", + "@esbuild/linux-x64": "0.25.8", + "@esbuild/netbsd-arm64": "0.25.8", + "@esbuild/netbsd-x64": "0.25.8", + "@esbuild/openbsd-arm64": "0.25.8", + "@esbuild/openbsd-x64": "0.25.8", + "@esbuild/openharmony-arm64": "0.25.8", + "@esbuild/sunos-x64": "0.25.8", + "@esbuild/win32-arm64": "0.25.8", + "@esbuild/win32-ia32": "0.25.8", + "@esbuild/win32-x64": "0.25.8" } }, "node_modules/esbuild-loader": { @@ -6572,9 +6630,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", - "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", "bin": { @@ -7008,14 +7066,11 @@ } }, "node_modules/eslint-plugin-playwright": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.0.tgz", - "integrity": "sha512-qSQpAw7RcSzE3zPp8FMGkthaCWovHZ/BsXtpmnGax9vQLIovlh1bsZHEa2+j2lv9DWhnyeLM/qZmp7ffQZfQvg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.2.2.tgz", + "integrity": "sha512-j0jKpndIPOXRRP9uMkwb9l/nSmModOU3452nrFdgFJoEv/435J1onk8+aITzjDW8DfypxgmVaDMdmVIa6F7I0w==", "dev": true, "license": "MIT", - "workspaces": [ - "examples" - ], "dependencies": { "globals": "^13.23.0" }, @@ -7027,9 +7082,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.1.tgz", - "integrity": "sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.3.tgz", + "integrity": "sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w==", "dev": true, "license": "MIT", "dependencies": { @@ -7182,9 +7237,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.3.0.tgz", - "integrity": "sha512-A0u9snqjCfYaPnqqOaH6MBLVWDUIN4trXn8J3x67uDcXvR7X6Ut8p16N+nYhMCQ9Y7edg2BIRGzfyZsY0IdqoQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.4.0.tgz", + "integrity": "sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw==", "dev": true, "license": "MIT", "dependencies": { @@ -7236,10 +7291,10 @@ "vue-eslint-parser": ">=7.1.0" } }, - "node_modules/eslint-plugin-vue-scoped-css/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "node_modules/eslint-plugin-vue/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "license": "MIT", "dependencies": { @@ -7467,9 +7522,9 @@ } }, "node_modules/expect-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", - "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -7999,9 +8054,9 @@ } }, "node_modules/happy-dom/node_modules/@types/node": { - "version": "20.19.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.4.tgz", - "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", + "version": "20.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", + "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", "dev": true, "license": "MIT", "dependencies": { @@ -8052,9 +8107,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.11.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.11.0.tgz", + "integrity": "sha512-aDdIN3GyU5I6wextPplYdfmWCo+aLmjjVbntmX6HLD5RCi/xKsivYEBhnRD+d9224zFf008ZpLMPlWF0ZodYZw==", "dev": true, "license": "MIT" }, @@ -9130,9 +9185,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.2.0", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz", + "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==", "dev": true, "license": "MIT" }, @@ -9376,14 +9431,14 @@ } }, "node_modules/mermaid": { - "version": "11.8.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.8.0.tgz", - "integrity": "sha512-uAZUwnBiqREZcUrFw3G5iQ5Pj3hTYUP95EZc3ec/nGBzHddJZydzYGE09tGZDBS1VoSoDn0symZ85FmypSTo5g==", + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.10.0.tgz", + "integrity": "sha512-oQsFzPBy9xlpnGxUqLbVY8pvknLlsNIJ0NWwi8SUJjhbP1IT0E0o1lfhU4iYV3ubpy+xkzkaOyDUQMn06vQElQ==", "license": "MIT", "dependencies": { "@braintree/sanitize-url": "^7.0.4", "@iconify/utils": "^2.1.33", - "@mermaid-js/parser": "^0.6.0", + "@mermaid-js/parser": "^0.6.2", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", @@ -9393,10 +9448,10 @@ "dagre-d3-es": "7.0.11", "dayjs": "^1.11.13", "dompurify": "^3.2.5", - "katex": "^0.16.9", + "katex": "^0.16.22", "khroma": "^2.1.0", "lodash-es": "^4.17.21", - "marked": "^15.0.7", + "marked": "^16.0.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", @@ -9404,15 +9459,15 @@ } }, "node_modules/mermaid/node_modules/marked": { - "version": "15.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", - "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.1.1.tgz", + "integrity": "sha512-ij/2lXfCRT71L6u0M29tJPhP0bM5shLL3u5BePhFwPELj2blMJ6GDtD7PfJhRLhJ/c2UwrK17ySVcDzy2YHjHQ==", "license": "MIT", "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 18" + "node": ">= 20" } }, "node_modules/micromark": { @@ -10152,9 +10207,9 @@ "license": "MIT" }, "node_modules/napi-postinstall": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.0.tgz", - "integrity": "sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.2.tgz", + "integrity": "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw==", "dev": true, "license": "MIT", "bin": { @@ -10736,13 +10791,13 @@ } }, "node_modules/playwright": { - "version": "1.53.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.53.2.tgz", - "integrity": "sha512-6K/qQxVFuVQhRQhFsVZ9fGeatxirtrpPgxzBYWyZLEXJzqYwuL4fuNmfOfD5et1tJE4GScKyPNeLhZeRwuTU3A==", + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.1.tgz", + "integrity": "sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.53.2" + "playwright-core": "1.54.1" }, "bin": { "playwright": "cli.js" @@ -10755,9 +10810,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.54.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.1.tgz", + "integrity": "sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10943,19 +10998,6 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-modules-scope": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", @@ -10971,19 +11013,6 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-modules-values": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", @@ -11024,6 +11053,19 @@ "postcss": "^8.2.14" } }, + "node_modules/postcss-nested/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-nesting": { "version": "13.0.2", "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.2.tgz", @@ -11051,63 +11093,6 @@ "postcss": "^8.4" } }, - "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.1.0.tgz", - "integrity": "sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, - "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, - "node_modules/postcss-nesting/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", @@ -11160,9 +11145,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -12278,9 +12263,9 @@ "license": "ISC" }, "node_modules/stylelint": { - "version": "16.21.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.21.1.tgz", - "integrity": "sha512-WCXdXnYK2tpCbebgMF0Bme3YZH/Rh/UXerj75twYo4uLULlcrLwFVdZTvTEF8idFnAcW21YUDJFyKOfaf6xJRw==", + "version": "16.23.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.23.1.tgz", + "integrity": "sha512-dNvDTsKV1U2YtiUDfe9d2gp902veFeo3ecCWdGlmLm2WFrAV0+L5LoOj/qHSBABQwMsZPJwfC4bf39mQm1S5zw==", "dev": true, "funding": [ { @@ -12307,7 +12292,7 @@ "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.3", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -12341,9 +12326,9 @@ } }, "node_modules/stylelint-config-recommended": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-16.0.0.tgz", - "integrity": "sha512-4RSmPjQegF34wNcK1e1O3Uz91HN8P1aFdFzio90wNK9mjgAI19u5vsU868cVZboKzCaa5XbpvtTzAAGQAxpcXA==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-17.0.0.tgz", + "integrity": "sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==", "dev": true, "funding": [ { @@ -12360,7 +12345,7 @@ "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.16.0" + "stylelint": "^16.23.0" } }, "node_modules/stylelint-declaration-block-no-ignored-properties": { @@ -12390,9 +12375,9 @@ } }, "node_modules/stylelint-define-config": { - "version": "16.21.0", - "resolved": "https://registry.npmjs.org/stylelint-define-config/-/stylelint-define-config-16.21.0.tgz", - "integrity": "sha512-DNbScaWa4MvOrEUgpUacIEBI57iV4drbIl9D5GXXlYtcv1z9xrdatDagewTq9uwXADodkwc3QJcraVAL/pWrWA==", + "version": "16.22.0", + "resolved": "https://registry.npmjs.org/stylelint-define-config/-/stylelint-define-config-16.22.0.tgz", + "integrity": "sha512-EEgHRugsryKo7LpenYyd4yLoZon3lHvRAi7WsMaZoRX9GPOkeDXrMga+N4VA4nK4Zus02EQwyYkndNQ64jaB2A==", "dev": true, "license": "MIT", "dependencies": { @@ -12424,71 +12409,24 @@ "stylelint": ">=16" } }, - "node_modules/stylelint/node_modules/@csstools/media-query-list-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", - "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/stylelint/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" - } - }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.1.tgz", - "integrity": "sha512-zcmsHjg2B2zjuBgjdnB+9q0+cWcgWfykIcsDkWDB4GTPtl1eXUA+gTI6sO0u01AqK3cliHryTU55/b2Ow1hfZg==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.3.tgz", + "integrity": "sha512-D+w75Ub8T55yor7fPgN06rkCAUbAYw2vpxJmmjv/GDAcvCnv9g7IvHhIZoxzRZThrXPFI2maeY24pPbtyYU7Lg==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.10" + "flat-cache": "^6.1.12" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.11.tgz", - "integrity": "sha512-zfOAns94mp7bHG/vCn9Ru2eDCmIxVQ5dELUHKjHfDEOJmHNzE+uGa6208kfkgmtym4a0FFjEuFksCXFacbVhSg==", + "version": "6.1.12", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.12.tgz", + "integrity": "sha512-U+HqqpZPPXP5d24bWuRzjGqVqUcw64k4nZAbruniDwdRg0H10tvN7H6ku1tjhA4rg5B9GS3siEvwO2qjJJ6f8Q==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.10.1", + "cacheable": "^1.10.3", "flatted": "^3.3.3", "hookified": "^1.10.0" } @@ -12530,20 +12468,6 @@ "postcss": "^8.4.31" } }, - "node_modules/stylelint/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/stylelint/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -12582,13 +12506,13 @@ } }, "node_modules/stylus/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">= 12" } }, "node_modules/sucrase": { @@ -12828,9 +12752,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.26.0.tgz", - "integrity": "sha512-U8m1LruHrk33gIIT5qDKhXMygT4FonRGBE92zMbxP4i9ULolPlKISy5Pd3RCES8pWdbGzXhvm/Q6jdA/HsrClg==", + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.27.0.tgz", + "integrity": "sha512-tS6LRyBhY6yAqxrfsA9IYpGWPUJOri6sclySa7TdC7XQfGLvTwDY531KLgfQwHEtQsn+sT4JlUspbeQDBVGWig==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -12850,13 +12774,13 @@ } }, "node_modules/synckit": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", - "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.4" + "@pkgr/core": "^0.2.9" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -12954,6 +12878,19 @@ } } }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/tapable": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", @@ -13116,9 +13053,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -13298,9 +13235,9 @@ } }, "node_modules/typo-js": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.5.tgz", - "integrity": "sha512-F45vFWdGX8xahIk/sOp79z2NJs8ETMYsmMChm9D5Hlx3+9j7VnCyQyvij5MOCrNY3NNe8noSyokRjQRfq+Bc7A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.3.0.tgz", + "integrity": "sha512-ERVoYp5PG7jpj7+kzKmFZfp5+IYMOOQM3etNnlYu06Z2CL5UmC9ekT8Z/JVYpR7e7sXB4bOFq1fz/budv++Z0g==", "license": "BSD-3-Clause" }, "node_modules/uc.micro": { @@ -13339,9 +13276,9 @@ } }, "node_modules/unrs-resolver": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.10.1.tgz", - "integrity": "sha512-EFrL7Hw4kmhZdwWO3dwwFJo6hO3FXuQ6Bg8BK/faHZ9m1YxqBS31BNSTxklIQkxK/4LlV8zTYnPsIRLBzTzjCA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -13352,25 +13289,25 @@ "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.10.1", - "@unrs/resolver-binding-android-arm64": "1.10.1", - "@unrs/resolver-binding-darwin-arm64": "1.10.1", - "@unrs/resolver-binding-darwin-x64": "1.10.1", - "@unrs/resolver-binding-freebsd-x64": "1.10.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.10.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.10.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.10.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.10.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.10.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.10.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.10.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.10.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.10.1", - "@unrs/resolver-binding-linux-x64-musl": "1.10.1", - "@unrs/resolver-binding-wasm32-wasi": "1.10.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.10.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.10.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.10.1" + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "node_modules/update-browserslist-db": { @@ -13404,16 +13341,16 @@ } }, "node_modules/updates": { - "version": "16.4.2", - "resolved": "https://registry.npmjs.org/updates/-/updates-16.4.2.tgz", - "integrity": "sha512-FCnbRnBUWrzhbsatc+RqUoLK7WB88VDGB9Jb1vB2JOx8gN69oXAE4/umtZsUzdeiM2TZ0aVb0kQJ0NbY8K21nw==", + "version": "16.5.2", + "resolved": "https://registry.npmjs.org/updates/-/updates-16.5.2.tgz", + "integrity": "sha512-CyxIT9TvUGe62hNWXW5FjbgNd8cPucqO5yrihmf+WgMtSUj31b4HyPuMsozxTnO0XQhTTLShIyV7ySJSSC5dsg==", "dev": true, "license": "BSD-2-Clause", "bin": { "updates": "dist/index.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/uri-js": { @@ -13490,15 +13427,15 @@ "license": "MIT" }, "node_modules/vite": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.2.tgz", - "integrity": "sha512-hxdyZDY1CM6SNpKI4w4lcUc3Mtkd9ej4ECWVHSMrOdSinVc2zYOAppHeGc/hzmRo3pxM5blMzkuWHOJA/3NiFw==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", + "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.6", - "picomatch": "^4.0.2", + "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.40.0", "tinyglobby": "^0.2.14" @@ -13588,9 +13525,9 @@ } }, "node_modules/vite-string-plugin": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/vite-string-plugin/-/vite-string-plugin-1.4.4.tgz", - "integrity": "sha512-mHcdjsDaJSBnUrsAb4L+AWamWVWSFwDb5JuBbU5hAOt1w/ixaQ0EwWx2gAZiqFfpl5XlSE0WmCp2ShbdwgqsvQ==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/vite-string-plugin/-/vite-string-plugin-1.4.6.tgz", + "integrity": "sha512-Csjtny8/uVIynzlaRRj4RpHrPAakNwlH9jw6kgQ8tQhc2f0zzA6bCbAgWD0y84EgB8aLNrz7pZFUqSt3LOtk+w==", "dev": true, "license": "BSD-2-Clause" }, @@ -13632,9 +13569,9 @@ } }, "node_modules/vite/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -13645,9 +13582,9 @@ } }, "node_modules/vite/node_modules/rollup": { - "version": "4.44.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.2.tgz", - "integrity": "sha512-PVoapzTwSEcelaWGth3uR66u7ZRo6qhPHc0f2uRO9fX6XDVNrIiGYS0Pj9+R8yIIYSD/mCx2b16Ws9itljKSPg==", + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", + "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", "dev": true, "license": "MIT", "dependencies": { @@ -13661,26 +13598,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.2", - "@rollup/rollup-android-arm64": "4.44.2", - "@rollup/rollup-darwin-arm64": "4.44.2", - "@rollup/rollup-darwin-x64": "4.44.2", - "@rollup/rollup-freebsd-arm64": "4.44.2", - "@rollup/rollup-freebsd-x64": "4.44.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.2", - "@rollup/rollup-linux-arm-musleabihf": "4.44.2", - "@rollup/rollup-linux-arm64-gnu": "4.44.2", - "@rollup/rollup-linux-arm64-musl": "4.44.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.2", - "@rollup/rollup-linux-riscv64-gnu": "4.44.2", - "@rollup/rollup-linux-riscv64-musl": "4.44.2", - "@rollup/rollup-linux-s390x-gnu": "4.44.2", - "@rollup/rollup-linux-x64-gnu": "4.44.2", - "@rollup/rollup-linux-x64-musl": "4.44.2", - "@rollup/rollup-win32-arm64-msvc": "4.44.2", - "@rollup/rollup-win32-ia32-msvc": "4.44.2", - "@rollup/rollup-win32-x64-msvc": "4.44.2", + "@rollup/rollup-android-arm-eabi": "4.46.2", + "@rollup/rollup-android-arm64": "4.46.2", + "@rollup/rollup-darwin-arm64": "4.46.2", + "@rollup/rollup-darwin-x64": "4.46.2", + "@rollup/rollup-freebsd-arm64": "4.46.2", + "@rollup/rollup-freebsd-x64": "4.46.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", + "@rollup/rollup-linux-arm-musleabihf": "4.46.2", + "@rollup/rollup-linux-arm64-gnu": "4.46.2", + "@rollup/rollup-linux-arm64-musl": "4.46.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", + "@rollup/rollup-linux-ppc64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-musl": "4.46.2", + "@rollup/rollup-linux-s390x-gnu": "4.46.2", + "@rollup/rollup-linux-x64-gnu": "4.46.2", + "@rollup/rollup-linux-x64-musl": "4.46.2", + "@rollup/rollup-win32-arm64-msvc": "4.46.2", + "@rollup/rollup-win32-ia32-msvc": "4.46.2", + "@rollup/rollup-win32-x64-msvc": "4.46.2", "fsevents": "~2.3.2" } }, @@ -13768,9 +13705,9 @@ } }, "node_modules/vitest/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -13837,16 +13774,16 @@ "license": "MIT" }, "node_modules/vue": { - "version": "3.5.17", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.17.tgz", - "integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==", + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.18.tgz", + "integrity": "sha512-7W4Y4ZbMiQ3SEo+m9lnoNpV9xG7QVMLa+/0RFwwiAVkeYoyGXqWE85jabU4pllJNUzqfLShJ5YLptewhCWUgNA==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.17", - "@vue/compiler-sfc": "3.5.17", - "@vue/runtime-dom": "3.5.17", - "@vue/server-renderer": "3.5.17", - "@vue/shared": "3.5.17" + "@vue/compiler-dom": "3.5.18", + "@vue/compiler-sfc": "3.5.18", + "@vue/runtime-dom": "3.5.18", + "@vue/server-renderer": "3.5.18", + "@vue/shared": "3.5.18" }, "peerDependencies": { "typescript": "*" @@ -13942,14 +13879,14 @@ } }, "node_modules/vue-tsc": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.0.1.tgz", - "integrity": "sha512-UvMLQD0hAGL1g/NfEQelnSVB4H5gtf/gz2lJKjMMwWNOUmSNyWkejwJagAxEbSjtV5CPPJYslOtoSuqJ63mhdg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.0.4.tgz", + "integrity": "sha512-kZmSEjGtROApVBuaIcoprrXZsFNGon5ggkTJokmhQ/H1hMzCFRPQ0Ed8IHYFsmYJYvHBcdmEQVGVcRuxzPzNbw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/typescript": "2.4.17", - "@vue/language-core": "3.0.1" + "@volar/typescript": "2.4.20", + "@vue/language-core": "3.0.4" }, "bin": { "vue-tsc": "bin/vue-tsc.js" @@ -13978,21 +13915,22 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.99.9", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", - "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.0.tgz", + "integrity": "sha512-B4t+nJqytPeuZlHuIKTbalhljIFXeNRqrUGAQgTGlfOl2lXXKXw+yZu6bicycP+PUlM44CxBjCFD6aciKFT3LQ==", "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", + "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", + "enhanced-resolve": "^5.17.2", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -14006,7 +13944,7 @@ "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" diff --git a/package.json b/package.json index 4b4f22351b2..1fe8bd021a6 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "@github/relative-time-element": "4.4.8", "@github/text-expander-element": "2.9.2", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", - "@primer/octicons": "19.15.3", + "@primer/octicons": "19.15.5", "@silverwind/vue3-calendar-heatmap": "2.0.6", "add-asset-webpack-plugin": "3.0.0", "ansi_up": "6.0.6", @@ -33,7 +33,7 @@ "jquery": "3.7.1", "katex": "0.16.22", "license-checker-webpack-plugin": "0.2.1", - "mermaid": "11.8.0", + "mermaid": "11.10.0", "mini-css-extract-plugin": "2.9.2", "minimatch": "10.0.3", "monaco-editor": "0.52.2", @@ -45,7 +45,7 @@ "postcss-loader": "8.1.1", "postcss-nesting": "13.0.2", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.26.0", + "swagger-ui-dist": "5.27.0", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", @@ -55,20 +55,20 @@ "typescript": "5.8.3", "uint8-to-base64": "0.2.1", "vanilla-colorful": "0.7.2", - "vue": "3.5.17", + "vue": "3.5.18", "vue-bar-graph": "2.2.0", "vue-chartjs": "5.3.2", "vue-loader": "17.4.2", - "webpack": "5.99.9", + "webpack": "5.101.0", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.0" }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.53.2", + "@playwright/test": "1.54.1", "@stoplight/spectral-cli": "6.15.0", "@stylistic/eslint-plugin-js": "3.1.0", - "@stylistic/stylelint-plugin": "3.1.3", + "@stylistic/stylelint-plugin": "4.0.0", "@types/dropzone": "5.7.9", "@types/jquery": "3.5.32", "@types/katex": "0.16.7", @@ -79,9 +79,9 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/eslint-plugin": "8.35.1", - "@typescript-eslint/parser": "8.35.1", - "@vitejs/plugin-vue": "6.0.0", + "@typescript-eslint/eslint-plugin": "8.38.0", + "@typescript-eslint/parser": "8.38.0", + "@vitejs/plugin-vue": "6.0.1", "@vitest/eslint-plugin": "1.3.4", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.4.4", @@ -90,11 +90,11 @@ "eslint-plugin-import-x": "4.16.1", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", - "eslint-plugin-playwright": "2.2.0", + "eslint-plugin-playwright": "2.2.2", "eslint-plugin-regexp": "2.9.0", "eslint-plugin-sonarjs": "3.0.4", "eslint-plugin-unicorn": "56.0.1", - "eslint-plugin-vue": "10.3.0", + "eslint-plugin-vue": "10.4.0", "eslint-plugin-vue-scoped-css": "2.11.0", "eslint-plugin-wc": "3.0.1", "happy-dom": "18.0.1", @@ -102,18 +102,18 @@ "material-icon-theme": "5.24.0", "nolyfill": "1.0.44", "postcss-html": "1.8.0", - "stylelint": "16.21.1", - "stylelint-config-recommended": "16.0.0", + "stylelint": "16.23.1", + "stylelint-config-recommended": "17.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", - "stylelint-define-config": "16.21.0", + "stylelint-define-config": "16.22.0", "stylelint-value-no-unknown-custom-properties": "6.0.1", "svgo": "4.0.0", "type-fest": "4.41.0", - "updates": "16.4.2", - "vite-string-plugin": "1.4.4", + "updates": "16.5.2", + "vite-string-plugin": "1.4.6", "vitest": "3.2.4", - "vue-tsc": "3.0.1" + "vue-tsc": "3.0.4" }, "browserslist": [ "defaults" diff --git a/public/assets/img/svg/octicon-agent.svg b/public/assets/img/svg/octicon-agent.svg new file mode 100644 index 00000000000..9e2bce0fef0 --- /dev/null +++ b/public/assets/img/svg/octicon-agent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/img/svg/octicon-loop.svg b/public/assets/img/svg/octicon-loop.svg new file mode 100644 index 00000000000..967641f1216 --- /dev/null +++ b/public/assets/img/svg/octicon-loop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/img/svg/octicon-mention.svg b/public/assets/img/svg/octicon-mention.svg index 75b414e123d..ff408c59a2f 100644 --- a/public/assets/img/svg/octicon-mention.svg +++ b/public/assets/img/svg/octicon-mention.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/img/svg/octicon-space.svg b/public/assets/img/svg/octicon-space.svg new file mode 100644 index 00000000000..22912be37a5 --- /dev/null +++ b/public/assets/img/svg/octicon-space.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/routers/api/v1/activitypub/person.go b/routers/api/v1/activitypub/person.go index 0b0db011c6a..f2ba2baf7fa 100644 --- a/routers/api/v1/activitypub/person.go +++ b/routers/api/v1/activitypub/person.go @@ -52,7 +52,7 @@ func Person(ctx *context.APIContext) { return } - person.URL = ap.IRI(ctx.ContextUser.HTMLURL()) + person.URL = ap.IRI(ctx.ContextUser.HTMLURL(ctx)) person.Icon = ap.Image{ Type: ap.ImageType, diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index f412e8a06ca..e185a2147c5 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -72,13 +72,13 @@ import ( actions_model "code.gitea.io/gitea/models/actions" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -780,7 +780,7 @@ func buildAuthGroup() *auth.Group { group.Add(&auth.ReverseProxy{}) } - if setting.IsWindows && auth_model.IsSSPIEnabled(db.DefaultContext) { + if setting.IsWindows && auth_model.IsSSPIEnabled(graceful.GetManager().ShutdownContext()) { group.Add(&auth.SSPI{}) // it MUST be the last, see the comment of SSPI } diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go index 99eef2f53b7..25aabe6dd27 100644 --- a/routers/api/v1/repo/action.go +++ b/routers/api/v1/repo/action.go @@ -1132,18 +1132,23 @@ func GetWorkflowRun(ctx *context.APIContext) { // "$ref": "#/responses/notFound" runID := ctx.PathParamInt64("run") - job, _, err := db.GetByID[actions_model.ActionRun](ctx, runID) - - if err != nil || job.RepoID != ctx.Repo.Repository.ID { - ctx.APIError(http.StatusNotFound, util.ErrNotExist) - } - - convertedArtifact, err := convert.ToActionWorkflowRun(ctx, ctx.Repo.Repository, job) + job, has, err := db.GetByID[actions_model.ActionRun](ctx, runID) if err != nil { ctx.APIErrorInternal(err) return } - ctx.JSON(http.StatusOK, convertedArtifact) + + if !has || job.RepoID != ctx.Repo.Repository.ID { + ctx.APIErrorNotFound(util.ErrNotExist) + return + } + + convertedRun, err := convert.ToActionWorkflowRun(ctx, ctx.Repo.Repository, job) + if err != nil { + ctx.APIErrorInternal(err) + return + } + ctx.JSON(http.StatusOK, convertedRun) } // ListWorkflowRunJobs Lists all jobs for a workflow run. @@ -1237,10 +1242,15 @@ func GetWorkflowJob(ctx *context.APIContext) { // "$ref": "#/responses/notFound" jobID := ctx.PathParamInt64("job_id") - job, _, err := db.GetByID[actions_model.ActionRunJob](ctx, jobID) + job, has, err := db.GetByID[actions_model.ActionRunJob](ctx, jobID) + if err != nil { + ctx.APIErrorInternal(err) + return + } - if err != nil || job.RepoID != ctx.Repo.Repository.ID { - ctx.APIError(http.StatusNotFound, util.ErrNotExist) + if !has || job.RepoID != ctx.Repo.Repository.ID { + ctx.APIErrorNotFound(util.ErrNotExist) + return } convertedWorkflowJob, err := convert.ToActionWorkflowJob(ctx, ctx.Repo.Repository, nil, job) @@ -1251,7 +1261,7 @@ func GetWorkflowJob(ctx *context.APIContext) { ctx.JSON(http.StatusOK, convertedWorkflowJob) } -// GetArtifacts Lists all artifacts for a repository. +// GetArtifactsOfRun Lists all artifacts for a repository. func GetArtifactsOfRun(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/actions/runs/{run}/artifacts repository getArtifactsOfRun // --- @@ -1354,7 +1364,7 @@ func DeleteActionRun(ctx *context.APIContext) { runID := ctx.PathParamInt64("run") run, err := actions_model.GetRunByRepoAndID(ctx, ctx.Repo.Repository.ID, runID) if errors.Is(err, util.ErrNotExist) { - ctx.APIError(http.StatusNotFound, err) + ctx.APIErrorNotFound(err) return } else if err != nil { ctx.APIErrorInternal(err) diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index feb9f1da64c..846e5f34655 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -721,8 +721,8 @@ func deleteIssueComment(ctx *context.APIContext) { if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) { ctx.Status(http.StatusForbidden) return - } else if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeCode { - ctx.Status(http.StatusNoContent) + } else if !comment.Type.HasContentSupport() { + ctx.Status(http.StatusBadRequest) return } diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 4b88ed0b781..e69b7729a0f 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -772,13 +772,8 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { var units []repo_model.RepoUnit var deleteUnitTypes []unit_model.Type - currHasIssues := repo.UnitEnabled(ctx, unit_model.TypeIssues) - newHasIssues := currHasIssues if opts.HasIssues != nil { - newHasIssues = *opts.HasIssues - } - if currHasIssues || newHasIssues { - if newHasIssues && opts.ExternalTracker != nil && !unit_model.TypeExternalTracker.UnitGlobalDisabled() { + if *opts.HasIssues && opts.ExternalTracker != nil && !unit_model.TypeExternalTracker.UnitGlobalDisabled() { // Check that values are valid if !validation.IsValidExternalURL(opts.ExternalTracker.ExternalTrackerURL) { err := errors.New("External tracker URL not valid") @@ -802,7 +797,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { }, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeIssues) - } else if newHasIssues && opts.ExternalTracker == nil && !unit_model.TypeIssues.UnitGlobalDisabled() { + } else if *opts.HasIssues && opts.ExternalTracker == nil && !unit_model.TypeIssues.UnitGlobalDisabled() { // Default to built-in tracker var config *repo_model.IssuesConfig @@ -829,7 +824,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { Config: config, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalTracker) - } else if !newHasIssues { + } else if !*opts.HasIssues { if !unit_model.TypeExternalTracker.UnitGlobalDisabled() { deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalTracker) } @@ -839,13 +834,8 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } } - currHasWiki := repo.UnitEnabled(ctx, unit_model.TypeWiki) - newHasWiki := currHasWiki if opts.HasWiki != nil { - newHasWiki = *opts.HasWiki - } - if currHasWiki || newHasWiki { - if newHasWiki && opts.ExternalWiki != nil && !unit_model.TypeExternalWiki.UnitGlobalDisabled() { + if *opts.HasWiki && opts.ExternalWiki != nil && !unit_model.TypeExternalWiki.UnitGlobalDisabled() { // Check that values are valid if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) { err := errors.New("External wiki URL not valid") @@ -861,7 +851,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { }, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeWiki) - } else if newHasWiki && opts.ExternalWiki == nil && !unit_model.TypeWiki.UnitGlobalDisabled() { + } else if *opts.HasWiki && opts.ExternalWiki == nil && !unit_model.TypeWiki.UnitGlobalDisabled() { config := &repo_model.UnitConfig{} units = append(units, repo_model.RepoUnit{ RepoID: repo.ID, @@ -869,7 +859,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { Config: config, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki) - } else if !newHasWiki { + } else if !*opts.HasWiki { if !unit_model.TypeExternalWiki.UnitGlobalDisabled() { deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki) } @@ -879,13 +869,20 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } } - currHasPullRequests := repo.UnitEnabled(ctx, unit_model.TypePullRequests) - newHasPullRequests := currHasPullRequests - if opts.HasPullRequests != nil { - newHasPullRequests = *opts.HasPullRequests + if opts.HasCode != nil && !unit_model.TypeCode.UnitGlobalDisabled() { + if *opts.HasCode { + units = append(units, repo_model.RepoUnit{ + RepoID: repo.ID, + Type: unit_model.TypeCode, + Config: &repo_model.UnitConfig{}, + }) + } else { + deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeCode) + } } - if currHasPullRequests || newHasPullRequests { - if newHasPullRequests && !unit_model.TypePullRequests.UnitGlobalDisabled() { + + if opts.HasPullRequests != nil && !unit_model.TypePullRequests.UnitGlobalDisabled() { + if *opts.HasPullRequests { // We do allow setting individual PR settings through the API, so // we get the config settings and then set them // if those settings were provided in the opts. @@ -953,18 +950,13 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { Type: unit_model.TypePullRequests, Config: config, }) - } else if !newHasPullRequests && !unit_model.TypePullRequests.UnitGlobalDisabled() { + } else { deleteUnitTypes = append(deleteUnitTypes, unit_model.TypePullRequests) } } - currHasProjects := repo.UnitEnabled(ctx, unit_model.TypeProjects) - newHasProjects := currHasProjects - if opts.HasProjects != nil { - newHasProjects = *opts.HasProjects - } - if currHasProjects || newHasProjects { - if newHasProjects && !unit_model.TypeProjects.UnitGlobalDisabled() { + if opts.HasProjects != nil && !unit_model.TypeProjects.UnitGlobalDisabled() { + if *opts.HasProjects { unit, err := repo.GetUnit(ctx, unit_model.TypeProjects) var config *repo_model.ProjectsConfig if err != nil { @@ -984,7 +976,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { Type: unit_model.TypeProjects, Config: config, }) - } else if !newHasProjects && !unit_model.TypeProjects.UnitGlobalDisabled() { + } else { deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeProjects) } } diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go index 40007ea1e5f..d632d5b5e12 100644 --- a/routers/api/v1/repo/status.go +++ b/routers/api/v1/repo/status.go @@ -271,11 +271,7 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) { } ctx.SetTotalCountHeader(count) - if len(statuses) == 0 { - ctx.JSON(http.StatusOK, &api.CombinedStatus{}) - return - } - - combiStatus := convert.ToCombinedStatus(ctx, statuses, convert.ToRepo(ctx, repo, ctx.Repo.Permission)) + combiStatus := convert.ToCombinedStatus(ctx, refCommit.Commit.ID.String(), statuses, + convert.ToRepo(ctx, repo, ctx.Repo.Permission)) ctx.JSON(http.StatusOK, combiStatus) } diff --git a/routers/init.go b/routers/init.go index 744feee2f0d..2281260a6fa 100644 --- a/routers/init.go +++ b/routers/init.go @@ -111,9 +111,9 @@ func InitWebInstallPage(ctx context.Context) { mustInit(svg.Init) } -// InitWebInstalled is for global installed configuration. +// InitWebInstalled is for the global configuration of an installed instance func InitWebInstalled(ctx context.Context) { - mustInitCtx(ctx, git.InitFull) + mustInit(git.InitFull) log.Info("Git version: %s (home: %s)", git.DefaultFeatures().VersionInfo(), git.HomeDir()) if !git.DefaultFeatures().SupportHashSha256 { log.Warn("sha256 hash support is disabled - requires Git >= 2.42." + util.Iif(git.DefaultFeatures().UsingGogit, " Gogit is currently unsupported.", "")) diff --git a/routers/install/install.go b/routers/install/install.go index dc8f209f3bd..4a9dabac6fe 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -180,20 +180,20 @@ func checkDatabase(ctx *context.Context, form *forms.InstallForm) bool { return false } - err = db_install.CheckDatabaseConnection() + err = db_install.CheckDatabaseConnection(ctx) if err != nil { ctx.Data["Err_DbSetting"] = true ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), tplInstall, form) return false } - hasPostInstallationUser, err := db_install.HasPostInstallationUsers() + hasPostInstallationUser, err := db_install.HasPostInstallationUsers(ctx) if err != nil { ctx.Data["Err_DbSetting"] = true ctx.RenderWithErr(ctx.Tr("install.invalid_db_table", "user", err), tplInstall, form) return false } - dbMigrationVersion, err := db_install.GetMigrationVersion() + dbMigrationVersion, err := db_install.GetMigrationVersion(ctx) if err != nil { ctx.Data["Err_DbSetting"] = true ctx.RenderWithErr(ctx.Tr("install.invalid_db_table", "version", err), tplInstall, form) diff --git a/routers/private/hook_post_receive_test.go b/routers/private/hook_post_receive_test.go index ca721b16d1b..23b8085e949 100644 --- a/routers/private/hook_post_receive_test.go +++ b/routers/private/hook_post_receive_test.go @@ -6,7 +6,6 @@ package private import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" pull_model "code.gitea.io/gitea/models/pull" repo_model "code.gitea.io/gitea/models/repo" @@ -21,13 +20,13 @@ import ( func TestHandlePullRequestMerging(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - pr, err := issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) + pr, err := issues_model.GetUnmergedPullRequest(t.Context(), 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) assert.NoError(t, err) - assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) + assert.NoError(t, pr.LoadBaseRepo(t.Context())) user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - err = pull_model.ScheduleAutoMerge(db.DefaultContext, user1, pr.ID, repo_model.MergeStyleSquash, "squash merge a pr", false) + err = pull_model.ScheduleAutoMerge(t.Context(), user1, pr.ID, repo_model.MergeStyleSquash, "squash merge a pr", false) assert.NoError(t, err) autoMerge := unittest.AssertExistsAndLoadBean(t, &pull_model.AutoMerge{PullID: pr.ID}) @@ -40,7 +39,7 @@ func TestHandlePullRequestMerging(t *testing.T) { {NewCommitID: "01234567"}, }) assert.Empty(t, resp.Body.String()) - pr, err = issues_model.GetPullRequestByID(db.DefaultContext, pr.ID) + pr, err = issues_model.GetPullRequestByID(t.Context(), pr.ID) assert.NoError(t, err) assert.True(t, pr.HasMerged) assert.Equal(t, "01234567", pr.MergedCommitID) diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go index 56c384b9709..fb1a7d95240 100644 --- a/routers/web/admin/auths.go +++ b/routers/web/admin/auths.go @@ -97,7 +97,7 @@ func NewAuthSource(ctx *context.Context) { ctx.Data["AuthSources"] = authSources ctx.Data["SecurityProtocols"] = securityProtocols ctx.Data["SMTPAuths"] = smtp.Authenticators - oauth2providers := oauth2.GetSupportedOAuth2Providers() + oauth2providers := oauth2.GetSupportedOAuth2Providers(ctx) ctx.Data["OAuth2Providers"] = oauth2providers ctx.Data["SSPIAutoCreateUsers"] = true @@ -107,7 +107,9 @@ func NewAuthSource(ctx *context.Context) { ctx.Data["SSPIDefaultLanguage"] = "" // only the first as default - ctx.Data["oauth2_provider"] = oauth2providers[0].Name() + if len(oauth2providers) > 0 { + ctx.Data["oauth2_provider"] = oauth2providers[0].Name() + } ctx.HTML(http.StatusOK, tplAuthNew) } @@ -240,7 +242,7 @@ func NewAuthSourcePost(ctx *context.Context) { ctx.Data["AuthSources"] = authSources ctx.Data["SecurityProtocols"] = securityProtocols ctx.Data["SMTPAuths"] = smtp.Authenticators - oauth2providers := oauth2.GetSupportedOAuth2Providers() + oauth2providers := oauth2.GetSupportedOAuth2Providers(ctx) ctx.Data["OAuth2Providers"] = oauth2providers ctx.Data["SSPIAutoCreateUsers"] = true @@ -332,7 +334,7 @@ func EditAuthSource(ctx *context.Context) { ctx.Data["SecurityProtocols"] = securityProtocols ctx.Data["SMTPAuths"] = smtp.Authenticators - oauth2providers := oauth2.GetSupportedOAuth2Providers() + oauth2providers := oauth2.GetSupportedOAuth2Providers(ctx) ctx.Data["OAuth2Providers"] = oauth2providers source, err := auth.GetSourceByID(ctx, ctx.PathParamInt64("authid")) @@ -366,7 +368,7 @@ func EditAuthSourcePost(ctx *context.Context) { ctx.Data["PageIsAdminAuthentications"] = true ctx.Data["SMTPAuths"] = smtp.Authenticators - oauth2providers := oauth2.GetSupportedOAuth2Providers() + oauth2providers := oauth2.GetSupportedOAuth2Providers(ctx) ctx.Data["OAuth2Providers"] = oauth2providers source, err := auth.GetSourceByID(ctx, ctx.PathParamInt64("authid")) diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 0e5b23db6d5..310ebd3f6d4 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -196,17 +196,21 @@ func ConfigSettings(ctx *context.Context) { } func ChangeConfig(ctx *context.Context) { - key := strings.TrimSpace(ctx.FormString("key")) - value := ctx.FormString("value") cfg := setting.Config() - marshalBool := func(v string) (string, error) { //nolint:unparam // error is always nil - if b, _ := strconv.ParseBool(v); b { - return "true", nil - } - return "false", nil + marshalBool := func(v string) ([]byte, error) { + b, _ := strconv.ParseBool(v) + return json.Marshal(b) } - marshalOpenWithApps := func(value string) (string, error) { + + marshalString := func(emptyDefault string) func(v string) ([]byte, error) { + return func(v string) ([]byte, error) { + return json.Marshal(util.IfZero(v, emptyDefault)) + } + } + + marshalOpenWithApps := func(value string) ([]byte, error) { + // TODO: move the block alongside OpenWithEditorAppsType.ToTextareaString lines := strings.Split(value, "\n") var openWithEditorApps setting.OpenWithEditorAppsType for _, line := range lines { @@ -224,32 +228,47 @@ func ChangeConfig(ctx *context.Context) { OpenURL: strings.TrimSpace(openURL), }) } - b, err := json.Marshal(openWithEditorApps) - if err != nil { - return "", err - } - return string(b), nil + return json.Marshal(openWithEditorApps) } - marshallers := map[string]func(string) (string, error){ + marshallers := map[string]func(string) ([]byte, error){ cfg.Picture.DisableGravatar.DynKey(): marshalBool, cfg.Picture.EnableFederatedAvatar.DynKey(): marshalBool, cfg.Repository.OpenWithEditorApps.DynKey(): marshalOpenWithApps, - } - marshaller, hasMarshaller := marshallers[key] - if !hasMarshaller { - ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) - return - } - marshaledValue, err := marshaller(value) - if err != nil { - ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) - return - } - if err = system_model.SetSettings(ctx, map[string]string{key: marshaledValue}); err != nil { - ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) - return + cfg.Repository.GitGuideRemoteName.DynKey(): marshalString(cfg.Repository.GitGuideRemoteName.DefaultValue()), } + _ = ctx.Req.ParseForm() + configKeys := ctx.Req.Form["key"] + configValues := ctx.Req.Form["value"] + configSettings := map[string]string{} +loop: + for i, key := range configKeys { + if i >= len(configValues) { + ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) + break loop + } + value := configValues[i] + + marshaller, hasMarshaller := marshallers[key] + if !hasMarshaller { + ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) + break loop + } + + marshaledValue, err := marshaller(value) + if err != nil { + ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) + break loop + } + configSettings[key] = string(marshaledValue) + } + if ctx.Written() { + return + } + if err := system_model.SetSettings(ctx, configSettings); err != nil { + ctx.ServerError("SetSettings", err) + return + } config.GetDynGetter().InvalidateCache() ctx.JSONOK() } diff --git a/routers/web/auth/auth_test.go b/routers/web/auth/auth_test.go index a0fd5c0e506..5ccffe0d505 100644 --- a/routers/web/auth/auth_test.go +++ b/routers/web/auth/auth_test.go @@ -9,7 +9,6 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/session" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" @@ -24,7 +23,7 @@ import ( func addOAuth2Source(t *testing.T, authName string, cfg oauth2.Source) { cfg.Provider = util.IfZero(cfg.Provider, "gitea") - err := auth_model.CreateSource(db.DefaultContext, &auth_model.Source{ + err := auth_model.CreateSource(t.Context(), &auth_model.Source{ Type: auth_model.OAuth2, Name: authName, IsActive: true, diff --git a/routers/web/auth/oauth_test.go b/routers/web/auth/oauth_test.go index 8d9365fab45..36b0cf6eace 100644 --- a/routers/web/auth/oauth_test.go +++ b/routers/web/auth/oauth_test.go @@ -7,7 +7,6 @@ import ( "testing" "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/services/oauth2_provider" @@ -21,7 +20,7 @@ func createAndParseToken(t *testing.T, grant *auth.OAuth2Grant) *oauth2_provider assert.NoError(t, err) assert.NotNil(t, signingKey) - response, terr := oauth2_provider.NewAccessTokenResponse(db.DefaultContext, grant, signingKey, signingKey) + response, terr := oauth2_provider.NewAccessTokenResponse(t.Context(), grant, signingKey, signingKey) assert.Nil(t, terr) assert.NotNil(t, response) @@ -43,7 +42,7 @@ func createAndParseToken(t *testing.T, grant *auth.OAuth2Grant) *oauth2_provider func TestNewAccessTokenResponse_OIDCToken(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - grants, err := auth.GetOAuth2GrantsByUserID(db.DefaultContext, 3) + grants, err := auth.GetOAuth2GrantsByUserID(t.Context(), 3) assert.NoError(t, err) assert.Len(t, grants, 1) @@ -59,7 +58,7 @@ func TestNewAccessTokenResponse_OIDCToken(t *testing.T) { assert.False(t, oidcToken.EmailVerified) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) - grants, err = auth.GetOAuth2GrantsByUserID(db.DefaultContext, user.ID) + grants, err = auth.GetOAuth2GrantsByUserID(t.Context(), user.ID) assert.NoError(t, err) assert.Len(t, grants, 1) @@ -67,8 +66,8 @@ func TestNewAccessTokenResponse_OIDCToken(t *testing.T) { oidcToken = createAndParseToken(t, grants[0]) assert.Equal(t, user.DisplayName(), oidcToken.Name) assert.Equal(t, user.Name, oidcToken.PreferredUsername) - assert.Equal(t, user.HTMLURL(), oidcToken.Profile) - assert.Equal(t, user.AvatarLink(db.DefaultContext), oidcToken.Picture) + assert.Equal(t, user.HTMLURL(t.Context()), oidcToken.Profile) + assert.Equal(t, user.AvatarLink(t.Context()), oidcToken.Picture) assert.Equal(t, user.Website, oidcToken.Website) assert.Equal(t, user.UpdatedUnix, oidcToken.UpdatedAt) assert.Equal(t, user.Email, oidcToken.Email) diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go index af48e6fb796..3774be033db 100644 --- a/routers/web/explore/user.go +++ b/routers/web/explore/user.go @@ -103,7 +103,7 @@ func RenderUserSearch(ctx *context.Context, opts user_model.SearchUserOptions, t if isSitemap { m := sitemap.NewSitemap() for _, item := range users { - m.Add(sitemap.URL{URL: item.HTMLURL(), LastMod: item.UpdatedUnix.AsTimePtr()}) + m.Add(sitemap.URL{URL: item.HTMLURL(ctx), LastMod: item.UpdatedUnix.AsTimePtr()}) } ctx.Resp.Header().Set("Content-Type", "text/xml") if _, err := m.WriteTo(ctx.Resp); err != nil { diff --git a/routers/web/feed/profile.go b/routers/web/feed/profile.go index cecf9d409ac..3ca4890e353 100644 --- a/routers/web/feed/profile.go +++ b/routers/web/feed/profile.go @@ -54,7 +54,7 @@ func showUserFeed(ctx *context.Context, formatType string) { return } - rctx := renderhelper.NewRenderContextSimpleDocument(ctx, ctx.ContextUser.HTMLURL()) + rctx := renderhelper.NewRenderContextSimpleDocument(ctx, ctx.ContextUser.HTMLURL(ctx)) ctxUserDescription, err := markdown.RenderString(rctx, ctx.ContextUser.Description) if err != nil { @@ -64,7 +64,7 @@ func showUserFeed(ctx *context.Context, formatType string) { feed := &feeds.Feed{ Title: ctx.Locale.TrString("home.feed_of", ctx.ContextUser.DisplayName()), - Link: &feeds.Link{Href: ctx.ContextUser.HTMLURL()}, + Link: &feeds.Link{Href: ctx.ContextUser.HTMLURL(ctx)}, Description: string(ctxUserDescription), Created: time.Now(), } diff --git a/routers/web/feed/render.go b/routers/web/feed/render.go index d1a229e5b27..014da253bdf 100644 --- a/routers/web/feed/render.go +++ b/routers/web/feed/render.go @@ -8,11 +8,18 @@ import ( ) // RenderBranchFeed render format for branch or file -func RenderBranchFeed(ctx *context.Context) { - _, showFeedType := GetFeedType(ctx.PathParam("reponame"), ctx.Req) +func RenderBranchFeed(ctx *context.Context, feedType string) { if ctx.Repo.TreePath == "" { - ShowBranchFeed(ctx, ctx.Repo.Repository, showFeedType) + ShowBranchFeed(ctx, ctx.Repo.Repository, feedType) } else { - ShowFileFeed(ctx, ctx.Repo.Repository, showFeedType) + ShowFileFeed(ctx, ctx.Repo.Repository, feedType) } } + +func RenderBranchFeedRSS(ctx *context.Context) { + RenderBranchFeed(ctx, "rss") +} + +func RenderBranchFeedAtom(ctx *context.Context) { + RenderBranchFeed(ctx, "atom") +} diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index 2bc1e8bc433..fe585b3a00b 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/modules/optional" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" @@ -25,7 +26,6 @@ import ( "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" org_service "code.gitea.io/gitea/services/org" - repo_service "code.gitea.io/gitea/services/repository" user_service "code.gitea.io/gitea/services/user" ) @@ -83,38 +83,17 @@ func SettingsPost(ctx *context.Context) { Description: optional.Some(form.Description), Website: optional.Some(form.Website), Location: optional.Some(form.Location), - Visibility: optional.Some(form.Visibility), RepoAdminChangeTeamAccess: optional.Some(form.RepoAdminChangeTeamAccess), } if ctx.Doer.IsAdmin { opts.MaxRepoCreation = optional.Some(form.MaxRepoCreation) } - visibilityChanged := org.Visibility != form.Visibility - if err := user_service.UpdateUser(ctx, org.AsUser(), opts); err != nil { ctx.ServerError("UpdateUser", err) return } - // update forks visibility - if visibilityChanged { - repos, _, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{ - Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos}, - }) - if err != nil { - ctx.ServerError("GetRepositories", err) - return - } - for _, repo := range repos { - repo.OwnerName = org.Name - if err := repo_service.UpdateRepository(ctx, repo, true); err != nil { - ctx.ServerError("UpdateRepository", err) - return - } - } - } - log.Trace("Organization setting updated: %s", org.Name) ctx.Flash.Success(ctx.Tr("org.settings.update_setting_success")) ctx.Redirect(ctx.Org.OrgLink + "/settings") @@ -251,3 +230,28 @@ func SettingsRenamePost(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("org.settings.rename_success", oldOrgName, newOrgName)) ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(newOrgName) + "/settings") } + +// SettingsChangeVisibilityPost response for change organization visibility +func SettingsChangeVisibilityPost(ctx *context.Context) { + visibility, ok := structs.VisibilityModes[ctx.FormString("visibility")] + if !ok { + ctx.Flash.Error(ctx.Tr("invalid_data", visibility)) + ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(ctx.Org.Organization.Name) + "/settings") + return + } + + if ctx.Org.Organization.Visibility == visibility { + ctx.Flash.Info(ctx.Tr("nothing_has_been_changed")) + ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(ctx.Org.Organization.Name) + "/settings") + return + } + + if err := org_service.ChangeOrganizationVisibility(ctx, ctx.Org.Organization, visibility); err != nil { + log.Error("ChangeOrganizationVisibility: %v", err) + ctx.JSONError(ctx.Tr("error.occurred")) + return + } + + ctx.Flash.Success(ctx.Tr("org.settings.change_visibility_success", ctx.Org.Organization.Name)) + ctx.JSONRedirect(setting.AppSubURL + "/org/" + url.PathEscape(ctx.Org.Organization.Name) + "/settings") +} diff --git a/routers/web/org/worktime.go b/routers/web/org/worktime.go index c7b44baf7bc..bf8db1a9a1a 100644 --- a/routers/web/org/worktime.go +++ b/routers/web/org/worktime.go @@ -58,13 +58,13 @@ func Worktime(ctx *context.Context) { var err error switch worktimeBy { case "milestones": - worktimeSumResult, err = organization.GetWorktimeByMilestones(ctx.Org.Organization, unixFrom, unixTo) + worktimeSumResult, err = organization.GetWorktimeByMilestones(ctx, ctx.Org.Organization, unixFrom, unixTo) ctx.Data["WorktimeByMilestones"] = true case "members": - worktimeSumResult, err = organization.GetWorktimeByMembers(ctx.Org.Organization, unixFrom, unixTo) + worktimeSumResult, err = organization.GetWorktimeByMembers(ctx, ctx.Org.Organization, unixFrom, unixTo) ctx.Data["WorktimeByMembers"] = true default: /* by repos */ - worktimeSumResult, err = organization.GetWorktimeByRepos(ctx.Org.Organization, unixFrom, unixTo) + worktimeSumResult, err = organization.GetWorktimeByRepos(ctx, ctx.Org.Organization, unixFrom, unixTo) ctx.Data["WorktimeByRepos"] = true } if err != nil { diff --git a/routers/web/repo/actions/actions_test.go b/routers/web/repo/actions/actions_test.go index 6a976ed65c0..9e83ff0fbba 100644 --- a/routers/web/repo/actions/actions_test.go +++ b/routers/web/repo/actions/actions_test.go @@ -162,7 +162,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) { func Test_loadIsRefDeleted(t *testing.T) { unittest.PrepareTestEnv(t) - runs, total, err := db.FindAndCount[actions_model.ActionRun](db.DefaultContext, + runs, total, err := db.FindAndCount[actions_model.ActionRun](t.Context(), actions_model.FindRunOptions{RepoID: 4, Ref: "refs/heads/test"}) assert.NoError(t, err) assert.Len(t, runs, 1) @@ -171,7 +171,7 @@ func Test_loadIsRefDeleted(t *testing.T) { assert.False(t, run.IsRefDeleted) } - assert.NoError(t, loadIsRefDeleted(db.DefaultContext, 4, runs)) + assert.NoError(t, loadIsRefDeleted(t.Context(), 4, runs)) for _, run := range runs { assert.True(t, run.IsRefDeleted) } diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 52b2e9995e3..3422128026f 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -429,6 +429,12 @@ func Rerun(ctx *context_module.Context) { ctx.ServerError("UpdateRun", err) return } + + if err := run.LoadAttributes(ctx); err != nil { + ctx.ServerError("run.LoadAttributes", err) + return + } + notify_service.WorkflowRunStatusUpdate(ctx, run.Repo, run.TriggerUser, run) } job, jobs := getRunJobs(ctx, runIndex, jobIndex) @@ -485,7 +491,6 @@ func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shou } actions_service.CreateCommitStatus(ctx, job) - actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, job) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) return nil @@ -560,9 +565,8 @@ func Cancel(ctx *context_module.Context) { if len(updatedjobs) > 0 { job := updatedjobs[0] actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, job) - notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) } - ctx.JSON(http.StatusOK, struct{}{}) + ctx.JSONOK() } func Approve(ctx *context_module.Context) { @@ -606,7 +610,6 @@ func Approve(ctx *context_module.Context) { if len(updatedjobs) > 0 { job := updatedjobs[0] actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, job) - notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) } for _, job := range updatedjobs { @@ -614,7 +617,7 @@ func Approve(ctx *context_module.Context) { notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) } - ctx.JSON(http.StatusOK, struct{}{}) + ctx.JSONOK() } func Delete(ctx *context_module.Context) { diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index 9a06c9359b5..0c60abcecd0 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -15,6 +15,7 @@ import ( asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" + issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/renderhelper" repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" @@ -411,6 +412,11 @@ func Diff(ctx *context.Context) { } } + pr, _ := issues_model.GetPullRequestByMergedCommit(ctx, ctx.Repo.Repository.ID, commitID) + if pr != nil { + ctx.Data["MergedPRIssueNumber"] = pr.Index + } + ctx.HTML(http.StatusOK, tplCommitPage) } diff --git a/routers/web/repo/editor_test.go b/routers/web/repo/editor_test.go index 6e2c1d62197..3ba75d5d706 100644 --- a/routers/web/repo/editor_test.go +++ b/routers/web/repo/editor_test.go @@ -8,7 +8,6 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "github.com/stretchr/testify/assert" @@ -22,7 +21,7 @@ func TestEditorUtils(t *testing.T) { assert.Equal(t, "user2-patch-1", branchName) }) t.Run("getClosestParentWithFiles", func(t *testing.T) { - gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) + gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo) defer gitRepo.Close() treePath := getClosestParentWithFiles(gitRepo, "sub-home-md-img-check", "docs/foo/bar") assert.Equal(t, "docs", treePath) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 9f71ab46329..bc58efeb6f6 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -643,8 +643,17 @@ func ViewPullCommits(ctx *context.Context) { ctx.HTML(http.StatusOK, tplPullCommits) } +func indexCommit(commits []*git.Commit, commitID string) *git.Commit { + for i := range commits { + if commits[i].ID.String() == commitID { + return commits[i] + } + } + return nil +} + // ViewPullFiles render pull request changed files list page -func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommit string, willShowSpecifiedCommitRange, willShowSpecifiedCommit bool) { +func viewPullFiles(ctx *context.Context, beforeCommitID, afterCommitID string) { ctx.Data["PageIsPullList"] = true ctx.Data["PageIsPullFiles"] = true @@ -654,11 +663,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi } pull := issue.PullRequest - var ( - startCommitID string - endCommitID string - gitRepo = ctx.Repo.GitRepo - ) + gitRepo := ctx.Repo.GitRepo prInfo := preparePullViewPullInfo(ctx, issue) if ctx.Written() { @@ -668,77 +673,68 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi return } - // Validate the given commit sha to show (if any passed) - if willShowSpecifiedCommit || willShowSpecifiedCommitRange { - foundStartCommit := len(specifiedStartCommit) == 0 - foundEndCommit := len(specifiedEndCommit) == 0 - - if !(foundStartCommit && foundEndCommit) { - for _, commit := range prInfo.Commits { - if commit.ID.String() == specifiedStartCommit { - foundStartCommit = true - } - if commit.ID.String() == specifiedEndCommit { - foundEndCommit = true - } - - if foundStartCommit && foundEndCommit { - break - } - } - } - - if !(foundStartCommit && foundEndCommit) { - ctx.NotFound(nil) - return - } - } - - if ctx.Written() { - return - } - headCommitID, err := gitRepo.GetRefCommitID(pull.GetGitHeadRefName()) if err != nil { ctx.ServerError("GetRefCommitID", err) return } - ctx.Data["IsShowingOnlySingleCommit"] = willShowSpecifiedCommit + isSingleCommit := beforeCommitID == "" && afterCommitID != "" + ctx.Data["IsShowingOnlySingleCommit"] = isSingleCommit + isShowAllCommits := (beforeCommitID == "" || beforeCommitID == prInfo.MergeBase) && (afterCommitID == "" || afterCommitID == headCommitID) + ctx.Data["IsShowingAllCommits"] = isShowAllCommits - if willShowSpecifiedCommit || willShowSpecifiedCommitRange { - if len(specifiedEndCommit) > 0 { - endCommitID = specifiedEndCommit + if afterCommitID == "" || afterCommitID == headCommitID { + afterCommitID = headCommitID + } + afterCommit := indexCommit(prInfo.Commits, afterCommitID) + if afterCommit == nil { + ctx.HTTPError(http.StatusBadRequest, "after commit not found in PR commits") + return + } + + var beforeCommit *git.Commit + if !isSingleCommit { + if beforeCommitID == "" || beforeCommitID == prInfo.MergeBase { + beforeCommitID = prInfo.MergeBase + // mergebase commit is not in the list of the pull request commits + beforeCommit, err = gitRepo.GetCommit(beforeCommitID) + if err != nil { + ctx.ServerError("GetCommit", err) + return + } } else { - endCommitID = headCommitID + beforeCommit = indexCommit(prInfo.Commits, beforeCommitID) + if beforeCommit == nil { + ctx.HTTPError(http.StatusBadRequest, "before commit not found in PR commits") + return + } } - if len(specifiedStartCommit) > 0 { - startCommitID = specifiedStartCommit - } else { - startCommitID = prInfo.MergeBase - } - ctx.Data["IsShowingAllCommits"] = false } else { - endCommitID = headCommitID - startCommitID = prInfo.MergeBase - ctx.Data["IsShowingAllCommits"] = true + beforeCommit, err = afterCommit.Parent(0) + if err != nil { + ctx.ServerError("Parent", err) + return + } + beforeCommitID = beforeCommit.ID.String() } ctx.Data["Username"] = ctx.Repo.Owner.Name ctx.Data["Reponame"] = ctx.Repo.Repository.Name - ctx.Data["AfterCommitID"] = endCommitID - ctx.Data["BeforeCommitID"] = startCommitID - - fileOnly := ctx.FormBool("file-only") + ctx.Data["MergeBase"] = prInfo.MergeBase + ctx.Data["AfterCommitID"] = afterCommitID + ctx.Data["BeforeCommitID"] = beforeCommitID maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles files := ctx.FormStrings("files") + fileOnly := ctx.FormBool("file-only") if fileOnly && (len(files) == 2 || len(files) == 1) { maxLines, maxFiles = -1, -1 } diffOptions := &gitdiff.DiffOptions{ - AfterCommitID: endCommitID, + BeforeCommitID: beforeCommitID, + AfterCommitID: afterCommitID, SkipTo: ctx.FormString("skip-to"), MaxLines: maxLines, MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters, @@ -746,10 +742,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)), } - if !willShowSpecifiedCommit { - diffOptions.BeforeCommitID = startCommitID - } - diff, err := gitdiff.GetDiffForRender(ctx, ctx.Repo.RepoLink, gitRepo, diffOptions, files...) if err != nil { ctx.ServerError("GetDiff", err) @@ -761,7 +753,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi // as the viewed information is designed to be loaded only on latest PR // diff and if you're signed in. var reviewState *pull_model.ReviewState - if ctx.IsSigned && !willShowSpecifiedCommit && !willShowSpecifiedCommitRange { + if ctx.IsSigned && isShowAllCommits { reviewState, err = gitdiff.SyncUserSpecificDiff(ctx, ctx.Doer.ID, pull, gitRepo, diff, diffOptions) if err != nil { ctx.ServerError("SyncUserSpecificDiff", err) @@ -769,7 +761,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi } } - diffShortStat, err := gitdiff.GetDiffShortStat(ctx.Repo.GitRepo, startCommitID, endCommitID) + diffShortStat, err := gitdiff.GetDiffShortStat(ctx.Repo.GitRepo, beforeCommitID, afterCommitID) if err != nil { ctx.ServerError("GetDiffShortStat", err) return @@ -816,7 +808,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi if !fileOnly { // note: use mergeBase is set to false because we already have the merge base from the pull request info - diffTree, err := gitdiff.GetDiffTree(ctx, gitRepo, false, startCommitID, endCommitID) + diffTree, err := gitdiff.GetDiffTree(ctx, gitRepo, false, beforeCommitID, afterCommitID) if err != nil { ctx.ServerError("GetDiffTree", err) return @@ -836,17 +828,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi ctx.Data["Diff"] = diff ctx.Data["DiffNotAvailable"] = diffShortStat.NumFiles == 0 - baseCommit, err := ctx.Repo.GitRepo.GetCommit(startCommitID) - if err != nil { - ctx.ServerError("GetCommit", err) - return - } - commit, err := gitRepo.GetCommit(endCommitID) - if err != nil { - ctx.ServerError("GetCommit", err) - return - } - if ctx.IsSigned && ctx.Doer != nil { if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, issue, ctx.Doer); err != nil { ctx.ServerError("CanMarkConversation", err) @@ -854,7 +835,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi } } - setCompareContext(ctx, baseCommit, commit, ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) + setCompareContext(ctx, beforeCommit, afterCommit, ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) assigneeUsers, err := repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository) if err != nil { @@ -901,7 +882,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi ctx.Data["CanBlockUser"] = func(blocker, blockee *user_model.User) bool { return user_service.CanBlockUser(ctx, ctx.Doer, blocker, blockee) } - if !willShowSpecifiedCommit && !willShowSpecifiedCommitRange && pull.Flow == issues_model.PullRequestFlowGithub { + if isShowAllCommits && pull.Flow == issues_model.PullRequestFlowGithub { if err := pull.LoadHeadRepo(ctx); err != nil { ctx.ServerError("LoadHeadRepo", err) return @@ -930,19 +911,17 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi } func ViewPullFilesForSingleCommit(ctx *context.Context) { - viewPullFiles(ctx, "", ctx.PathParam("sha"), true, true) + // it doesn't support showing files from mergebase to the special commit + // otherwise it will be ambiguous + viewPullFiles(ctx, "", ctx.PathParam("sha")) } func ViewPullFilesForRange(ctx *context.Context) { - viewPullFiles(ctx, ctx.PathParam("shaFrom"), ctx.PathParam("shaTo"), true, false) -} - -func ViewPullFilesStartingFromCommit(ctx *context.Context) { - viewPullFiles(ctx, "", ctx.PathParam("sha"), true, false) + viewPullFiles(ctx, ctx.PathParam("shaFrom"), ctx.PathParam("shaTo")) } func ViewPullFilesForAllCommitsOfPr(ctx *context.Context) { - viewPullFiles(ctx, "", "", false, false) + viewPullFiles(ctx, "", "") } // UpdatePullRequest merge PR's baseBranch into headBranch diff --git a/routers/web/repo/pull_review_test.go b/routers/web/repo/pull_review_test.go index 3d0997ab4d8..42223c1d9c6 100644 --- a/routers/web/repo/pull_review_test.go +++ b/routers/web/repo/pull_review_test.go @@ -23,10 +23,10 @@ import ( func TestRenderConversation(t *testing.T) { unittest.PrepareTestEnv(t) - pr, _ := issues_model.GetPullRequestByID(db.DefaultContext, 2) - _ = pr.LoadIssue(db.DefaultContext) - _ = pr.Issue.LoadPoster(db.DefaultContext) - _ = pr.Issue.LoadRepo(db.DefaultContext) + pr, _ := issues_model.GetPullRequestByID(t.Context(), 2) + _ = pr.LoadIssue(t.Context()) + _ = pr.Issue.LoadPoster(t.Context()) + _ = pr.Issue.LoadRepo(t.Context()) run := func(name string, cb func(t *testing.T, ctx *context.Context, resp *httptest.ResponseRecorder)) { t.Run(name, func(t *testing.T) { @@ -73,7 +73,7 @@ func TestRenderConversation(t *testing.T) { assert.Contains(t, resp.Body.String(), `
0 { - job := jobs[0] - notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) - } + job := jobs[0] + notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) } } @@ -101,7 +99,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { return nil } -// CancelAbandonedJobs cancels the jobs which have waiting status, but haven't been picked by a runner for a long time +// CancelAbandonedJobs cancels jobs that have not been picked by any runner for a long time func CancelAbandonedJobs(ctx context.Context) error { jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{ Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked}, @@ -113,24 +111,40 @@ func CancelAbandonedJobs(ctx context.Context) error { } now := timeutil.TimeStampNow() + + // Collect one job per run to send workflow run status update + updatedRuns := map[int64]*actions_model.ActionRunJob{} + for _, job := range jobs { job.Status = actions_model.StatusCancelled job.Stopped = now updated := false if err := db.WithTx(ctx, func(ctx context.Context) error { n, err := actions_model.UpdateRunJob(ctx, job, nil, "status", "stopped") - updated = err == nil && n > 0 - return err + if err != nil { + return err + } + if err := job.LoadAttributes(ctx); err != nil { + return err + } + updated = n > 0 + if updated && job.Run.Status.IsDone() { + updatedRuns[job.RunID] = job + } + return nil }); err != nil { log.Warn("cancel abandoned job %v: %v", job.ID, err) // go on } CreateCommitStatus(ctx, job) if updated { - NotifyWorkflowRunStatusUpdateWithReload(ctx, job) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) } } + for _, job := range updatedRuns { + notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) + } + return nil } diff --git a/services/actions/init_test.go b/services/actions/init_test.go index 7ef07022041..2d33a4e5cc3 100644 --- a/services/actions/init_test.go +++ b/services/actions/init_test.go @@ -25,10 +25,10 @@ func TestInitToken(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) t.Run("NoToken", func(t *testing.T) { - _, _ = db.Exec(db.DefaultContext, "DELETE FROM action_runner_token") + _, _ = db.Exec(t.Context(), "DELETE FROM action_runner_token") t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "") t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", "") - err := initGlobalRunnerToken(db.DefaultContext) + err := initGlobalRunnerToken(t.Context()) require.NoError(t, err) notEmpty, err := db.IsTableNotEmpty(&actions_model.ActionRunnerToken{}) require.NoError(t, err) @@ -39,13 +39,13 @@ func TestInitToken(t *testing.T) { tokenValue, _ := util.CryptoRandomString(32) t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", tokenValue) t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", "") - err := initGlobalRunnerToken(db.DefaultContext) + err := initGlobalRunnerToken(t.Context()) require.NoError(t, err) token := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue}) assert.True(t, token.IsActive) // init with the same token again, should not create a new token - err = initGlobalRunnerToken(db.DefaultContext) + err = initGlobalRunnerToken(t.Context()) require.NoError(t, err) token2 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue}) assert.Equal(t, token.ID, token2.ID) @@ -58,13 +58,13 @@ func TestInitToken(t *testing.T) { _ = os.WriteFile(f, []byte(tokenValue), 0o644) t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "") t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN_FILE", f) - err := initGlobalRunnerToken(db.DefaultContext) + err := initGlobalRunnerToken(t.Context()) require.NoError(t, err) token := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue}) assert.True(t, token.IsActive) // if the env token is invalidated by another new token, then it shouldn't be active anymore - _, err = actions_model.NewRunnerToken(db.DefaultContext, 0, 0) + _, err = actions_model.NewRunnerToken(t.Context(), 0, 0) require.NoError(t, err) token = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunnerToken{Token: tokenValue}) assert.False(t, token.IsActive) @@ -72,7 +72,7 @@ func TestInitToken(t *testing.T) { t.Run("InvalidToken", func(t *testing.T) { t.Setenv("GITEA_RUNNER_REGISTRATION_TOKEN", "abc") - err := initGlobalRunnerToken(db.DefaultContext) + err := initGlobalRunnerToken(t.Context()) assert.ErrorContains(t, err, "must be at least") }) } diff --git a/services/actions/notifier.go b/services/actions/notifier.go index d10cc0ab344..110e330f68d 100644 --- a/services/actions/notifier.go +++ b/services/actions/notifier.go @@ -263,11 +263,6 @@ func (n *actionsNotifier) CreateIssueComment(ctx context.Context, doer *user_mod func (n *actionsNotifier) UpdateComment(ctx context.Context, doer *user_model.User, c *issues_model.Comment, oldContent string) { ctx = withMethod(ctx, "UpdateComment") - if err := c.LoadIssue(ctx); err != nil { - log.Error("LoadIssue: %v", err) - return - } - if c.Issue.IsPull { notifyIssueCommentChange(ctx, doer, c, oldContent, webhook_module.HookEventPullRequestComment, api.HookIssueCommentEdited) return @@ -278,11 +273,6 @@ func (n *actionsNotifier) UpdateComment(ctx context.Context, doer *user_model.Us func (n *actionsNotifier) DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_model.Comment) { ctx = withMethod(ctx, "DeleteComment") - if err := comment.LoadIssue(ctx); err != nil { - log.Error("LoadIssue: %v", err) - return - } - if comment.Issue.IsPull { notifyIssueCommentChange(ctx, doer, comment, "", webhook_module.HookEventPullRequestComment, api.HookIssueCommentDeleted) return @@ -291,6 +281,7 @@ func (n *actionsNotifier) DeleteComment(ctx context.Context, doer *user_model.Us } func notifyIssueCommentChange(ctx context.Context, doer *user_model.User, comment *issues_model.Comment, oldContent string, event webhook_module.HookEventType, action api.HookIssueCommentAction) { + comment.Issue = nil // force issue to be loaded if err := comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index f94462ea463..8fd2adc8b48 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -69,6 +69,29 @@ func signingModeFromStrings(modeStrings []string) []signingMode { return returnable } +func userHasPubkeysGPG(ctx context.Context, userID int64) (bool, error) { + return db.Exist[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ + OwnerID: userID, + IncludeSubKeys: true, + }.ToConds()) +} + +func userHasPubkeysSSH(ctx context.Context, userID int64) (bool, error) { + return db.Exist[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ + OwnerID: userID, + NotKeytype: asymkey_model.KeyTypePrincipal, + }.ToConds()) +} + +// userHasPubkeys checks if a user has any public keys (GPG or SSH) +func userHasPubkeys(ctx context.Context, userID int64) (bool, error) { + has, err := userHasPubkeysGPG(ctx, userID) + if has || err != nil { + return has, err + } + return userHasPubkeysSSH(ctx, userID) +} + // ErrWontSign explains the first reason why a commit would not be signed // There may be other reasons - this is just the first reason found type ErrWontSign struct { @@ -170,14 +193,11 @@ Loop: case always: break Loop case pubkey: - keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ - OwnerID: u.ID, - IncludeSubKeys: true, - }) + hasKeys, err := userHasPubkeys(ctx, u.ID) if err != nil { return false, nil, nil, err } - if len(keys) == 0 { + if !hasKeys { return false, nil, nil, &ErrWontSign{pubkey} } case twofa: @@ -210,14 +230,11 @@ Loop: case always: break Loop case pubkey: - keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ - OwnerID: u.ID, - IncludeSubKeys: true, - }) + hasKeys, err := userHasPubkeys(ctx, u.ID) if err != nil { return false, nil, nil, err } - if len(keys) == 0 { + if !hasKeys { return false, nil, nil, &ErrWontSign{pubkey} } case twofa: @@ -266,14 +283,11 @@ Loop: case always: break Loop case pubkey: - keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ - OwnerID: u.ID, - IncludeSubKeys: true, - }) + hasKeys, err := userHasPubkeys(ctx, u.ID) if err != nil { return false, nil, nil, err } - if len(keys) == 0 { + if !hasKeys { return false, nil, nil, &ErrWontSign{pubkey} } case twofa: @@ -290,16 +304,22 @@ Loop: return false, nil, nil, err } defer gitRepo.Close() - commit, err := gitRepo.GetCommit(parentCommit) + isEmpty, err := gitRepo.IsEmpty() if err != nil { return false, nil, nil, err } - if commit.Signature == nil { - return false, nil, nil, &ErrWontSign{parentSigned} - } - verification := ParseCommitWithSignature(ctx, commit) - if !verification.Verified { - return false, nil, nil, &ErrWontSign{parentSigned} + if !isEmpty { + commit, err := gitRepo.GetCommit(parentCommit) + if err != nil { + return false, nil, nil, err + } + if commit.Signature == nil { + return false, nil, nil, &ErrWontSign{parentSigned} + } + verification := ParseCommitWithSignature(ctx, commit) + if !verification.Verified { + return false, nil, nil, &ErrWontSign{parentSigned} + } } } } @@ -331,14 +351,11 @@ Loop: case always: break Loop case pubkey: - keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ - OwnerID: u.ID, - IncludeSubKeys: true, - }) + hasKeys, err := userHasPubkeys(ctx, u.ID) if err != nil { return false, nil, nil, err } - if len(keys) == 0 { + if !hasKeys { return false, nil, nil, &ErrWontSign{pubkey} } case twofa: diff --git a/services/asymkey/sign_test.go b/services/asymkey/sign_test.go new file mode 100644 index 00000000000..fbcf078cf80 --- /dev/null +++ b/services/asymkey/sign_test.go @@ -0,0 +1,39 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package asymkey + +import ( + "testing" + + "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUserHasPubkeys(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + test := func(t *testing.T, userID int64, expectedHasGPG, expectedHasSSH bool) { + ctx := t.Context() + hasGPG, err := userHasPubkeysGPG(ctx, userID) + require.NoError(t, err) + hasSSH, err := userHasPubkeysSSH(ctx, userID) + require.NoError(t, err) + hasPubkeys, err := userHasPubkeys(ctx, userID) + require.NoError(t, err) + assert.Equal(t, expectedHasGPG, hasGPG) + assert.Equal(t, expectedHasSSH, hasSSH) + assert.Equal(t, expectedHasGPG || expectedHasSSH, hasPubkeys) + } + + t.Run("AllowUserWithGPGKey", func(t *testing.T) { + test(t, 36, true, false) // has gpg + }) + t.Run("AllowUserWithSSHKey", func(t *testing.T) { + test(t, 2, false, true) // has ssh + }) + t.Run("DenyUserWithNoKeys", func(t *testing.T) { + test(t, 1, false, false) // no pubkey + }) +} diff --git a/services/asymkey/ssh_key_test.go b/services/asymkey/ssh_key_test.go index fbd5d13ab2d..3605bd1e64c 100644 --- a/services/asymkey/ssh_key_test.go +++ b/services/asymkey/ssh_key_test.go @@ -66,8 +66,8 @@ ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ib for i, kase := range testCases { s.ID = int64(i) + 20 - asymkey_model.AddPublicKeysBySource(db.DefaultContext, user, s, []string{kase.keyString}) - keys, err := db.Find[asymkey_model.PublicKey](db.DefaultContext, asymkey_model.FindPublicKeyOptions{ + asymkey_model.AddPublicKeysBySource(t.Context(), user, s, []string{kase.keyString}) + keys, err := db.Find[asymkey_model.PublicKey](t.Context(), asymkey_model.FindPublicKeyOptions{ OwnerID: user.ID, LoginSourceID: s.ID, }) @@ -81,7 +81,7 @@ ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ib assert.Contains(t, kase.keyContents, key.Content) } for _, key := range keys { - DeletePublicKey(db.DefaultContext, user, key.ID) + DeletePublicKey(t.Context(), user, key.ID) } } } diff --git a/services/attachment/attachment_test.go b/services/attachment/attachment_test.go index 65475836bec..8ecac8d7a33 100644 --- a/services/attachment/attachment_test.go +++ b/services/attachment/attachment_test.go @@ -8,7 +8,6 @@ import ( "path/filepath" "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -32,14 +31,14 @@ func TestUploadAttachment(t *testing.T) { assert.NoError(t, err) defer f.Close() - attach, err := NewAttachment(db.DefaultContext, &repo_model.Attachment{ + attach, err := NewAttachment(t.Context(), &repo_model.Attachment{ RepoID: 1, UploaderID: user.ID, Name: filepath.Base(fPath), }, f, -1) assert.NoError(t, err) - attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, attach.UUID) + attachment, err := repo_model.GetAttachmentByUUID(t.Context(), attach.UUID) assert.NoError(t, err) assert.Equal(t, user.ID, attachment.UploaderID) assert.Equal(t, int64(0), attachment.DownloadCount) diff --git a/services/auth/auth_token_test.go b/services/auth/auth_token_test.go index 23c8d17e597..6b04caab853 100644 --- a/services/auth/auth_token_test.go +++ b/services/auth/auth_token_test.go @@ -8,7 +8,6 @@ import ( "time" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/timeutil" @@ -19,19 +18,19 @@ func TestCheckAuthToken(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) t.Run("Empty", func(t *testing.T) { - token, err := CheckAuthToken(db.DefaultContext, "") + token, err := CheckAuthToken(t.Context(), "") assert.NoError(t, err) assert.Nil(t, token) }) t.Run("InvalidFormat", func(t *testing.T) { - token, err := CheckAuthToken(db.DefaultContext, "dummy") + token, err := CheckAuthToken(t.Context(), "dummy") assert.ErrorIs(t, err, ErrAuthTokenInvalidFormat) assert.Nil(t, token) }) t.Run("NotFound", func(t *testing.T) { - token, err := CheckAuthToken(db.DefaultContext, "notexists:dummy") + token, err := CheckAuthToken(t.Context(), "notexists:dummy") assert.ErrorIs(t, err, ErrAuthTokenExpired) assert.Nil(t, token) }) @@ -39,44 +38,44 @@ func TestCheckAuthToken(t *testing.T) { t.Run("Expired", func(t *testing.T) { timeutil.MockSet(time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)) - at, token, err := CreateAuthTokenForUserID(db.DefaultContext, 2) + at, token, err := CreateAuthTokenForUserID(t.Context(), 2) assert.NoError(t, err) assert.NotNil(t, at) assert.NotEmpty(t, token) timeutil.MockUnset() - at2, err := CheckAuthToken(db.DefaultContext, at.ID+":"+token) + at2, err := CheckAuthToken(t.Context(), at.ID+":"+token) assert.ErrorIs(t, err, ErrAuthTokenExpired) assert.Nil(t, at2) - assert.NoError(t, auth_model.DeleteAuthTokenByID(db.DefaultContext, at.ID)) + assert.NoError(t, auth_model.DeleteAuthTokenByID(t.Context(), at.ID)) }) t.Run("InvalidHash", func(t *testing.T) { - at, token, err := CreateAuthTokenForUserID(db.DefaultContext, 2) + at, token, err := CreateAuthTokenForUserID(t.Context(), 2) assert.NoError(t, err) assert.NotNil(t, at) assert.NotEmpty(t, token) - at2, err := CheckAuthToken(db.DefaultContext, at.ID+":"+token+"dummy") + at2, err := CheckAuthToken(t.Context(), at.ID+":"+token+"dummy") assert.ErrorIs(t, err, ErrAuthTokenInvalidHash) assert.Nil(t, at2) - assert.NoError(t, auth_model.DeleteAuthTokenByID(db.DefaultContext, at.ID)) + assert.NoError(t, auth_model.DeleteAuthTokenByID(t.Context(), at.ID)) }) t.Run("Valid", func(t *testing.T) { - at, token, err := CreateAuthTokenForUserID(db.DefaultContext, 2) + at, token, err := CreateAuthTokenForUserID(t.Context(), 2) assert.NoError(t, err) assert.NotNil(t, at) assert.NotEmpty(t, token) - at2, err := CheckAuthToken(db.DefaultContext, at.ID+":"+token) + at2, err := CheckAuthToken(t.Context(), at.ID+":"+token) assert.NoError(t, err) assert.NotNil(t, at2) - assert.NoError(t, auth_model.DeleteAuthTokenByID(db.DefaultContext, at.ID)) + assert.NoError(t, auth_model.DeleteAuthTokenByID(t.Context(), at.ID)) }) } @@ -86,14 +85,14 @@ func TestRegenerateAuthToken(t *testing.T) { timeutil.MockSet(time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)) defer timeutil.MockUnset() - at, token, err := CreateAuthTokenForUserID(db.DefaultContext, 2) + at, token, err := CreateAuthTokenForUserID(t.Context(), 2) assert.NoError(t, err) assert.NotNil(t, at) assert.NotEmpty(t, token) timeutil.MockSet(time.Date(2023, 1, 1, 0, 0, 1, 0, time.UTC)) - at2, token2, err := RegenerateAuthToken(db.DefaultContext, at) + at2, token2, err := RegenerateAuthToken(t.Context(), at) assert.NoError(t, err) assert.NotNil(t, at2) assert.NotEmpty(t, token2) @@ -103,5 +102,5 @@ func TestRegenerateAuthToken(t *testing.T) { assert.NotEqual(t, token, token2) assert.NotEqual(t, at.ExpiresUnix, at2.ExpiresUnix) - assert.NoError(t, auth_model.DeleteAuthTokenByID(db.DefaultContext, at.ID)) + assert.NoError(t, auth_model.DeleteAuthTokenByID(t.Context(), at.ID)) } diff --git a/services/auth/source/oauth2/providers.go b/services/auth/source/oauth2/providers.go index 75ed41ba668..bb21cb53fe6 100644 --- a/services/auth/source/oauth2/providers.go +++ b/services/auth/source/oauth2/providers.go @@ -10,6 +10,7 @@ import ( "html" "html/template" "net/url" + "slices" "sort" "code.gitea.io/gitea/models/auth" @@ -75,6 +76,10 @@ func (p *AuthSourceProvider) IconHTML(size int) template.HTML { // value is used to store display data var gothProviders = map[string]GothProvider{} +func isAzureProvider(name string) bool { + return name == "azuread" || name == "microsoftonline" || name == "azureadv2" +} + // RegisterGothProvider registers a GothProvider func RegisterGothProvider(provider GothProvider) { if _, has := gothProviders[provider.Name()]; has { @@ -83,13 +88,42 @@ func RegisterGothProvider(provider GothProvider) { gothProviders[provider.Name()] = provider } -// GetSupportedOAuth2Providers returns the map of unconfigured OAuth2 providers +// getExistingAzureADAuthSources returns a list of Azure AD provider names that are already configured +func getExistingAzureADAuthSources(ctx context.Context) ([]string, error) { + authSources, err := db.Find[auth.Source](ctx, auth.FindSourcesOptions{ + LoginType: auth.OAuth2, + }) + if err != nil { + return nil, err + } + + var existingAzureProviders []string + for _, source := range authSources { + if oauth2Cfg, ok := source.Cfg.(*Source); ok { + if isAzureProvider(oauth2Cfg.Provider) { + existingAzureProviders = append(existingAzureProviders, oauth2Cfg.Provider) + } + } + } + return existingAzureProviders, nil +} + +// GetSupportedOAuth2Providers returns the list of supported OAuth2 providers with context for filtering // key is used as technical name (like in the callbackURL) // values to display -func GetSupportedOAuth2Providers() []Provider { +// Note: Azure AD providers (azuread, microsoftonline, azureadv2) are filtered out +// unless they already exist in the system to encourage use of OpenID Connect +func GetSupportedOAuth2Providers(ctx context.Context) []Provider { providers := make([]Provider, 0, len(gothProviders)) + existingAzureSources, err := getExistingAzureADAuthSources(ctx) + if err != nil { + log.Error("Failed to get existing OAuth2 auth sources: %v", err) + } for _, provider := range gothProviders { + if isAzureProvider(provider.Name()) && !slices.Contains(existingAzureSources, provider.Name()) { + continue + } providers = append(providers, provider) } sort.Slice(providers, func(i, j int) bool { diff --git a/services/convert/issue.go b/services/convert/issue.go index 7f386e62933..ecb3b93af1a 100644 --- a/services/convert/issue.go +++ b/services/convert/issue.go @@ -66,7 +66,7 @@ func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Iss return &api.Issue{} } apiIssue.URL = issue.APIURL(ctx) - apiIssue.HTMLURL = issue.HTMLURL() + apiIssue.HTMLURL = issue.HTMLURL(ctx) if err := issue.LoadLabels(ctx); err != nil { return &api.Issue{} } @@ -112,7 +112,7 @@ func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Iss apiIssue.PullRequest.Merged = issue.PullRequest.MergedUnix.AsTimePtr() } // Add pr's html url - apiIssue.PullRequest.HTMLURL = issue.HTMLURL() + apiIssue.PullRequest.HTMLURL = issue.HTMLURL(ctx) } } if issue.DeadlineUnix != 0 { diff --git a/services/convert/notification.go b/services/convert/notification.go index 41063cf399f..69470638be8 100644 --- a/services/convert/notification.go +++ b/services/convert/notification.go @@ -40,7 +40,7 @@ func ToNotificationThread(ctx context.Context, n *activities_model.Notification) if n.Issue != nil { result.Subject.Title = n.Issue.Title result.Subject.URL = n.Issue.APIURL(ctx) - result.Subject.HTMLURL = n.Issue.HTMLURL() + result.Subject.HTMLURL = n.Issue.HTMLURL(ctx) result.Subject.State = n.Issue.State() comment, err := n.Issue.GetLastComment(ctx) if err == nil && comment != nil { @@ -53,7 +53,7 @@ func ToNotificationThread(ctx context.Context, n *activities_model.Notification) if n.Issue != nil { result.Subject.Title = n.Issue.Title result.Subject.URL = n.Issue.APIURL(ctx) - result.Subject.HTMLURL = n.Issue.HTMLURL() + result.Subject.HTMLURL = n.Issue.HTMLURL(ctx) result.Subject.State = n.Issue.State() comment, err := n.Issue.GetLastComment(ctx) if err == nil && comment != nil { diff --git a/services/convert/package.go b/services/convert/package.go index b27992bea9e..08310dd7f6d 100644 --- a/services/convert/package.go +++ b/services/convert/package.go @@ -35,7 +35,7 @@ func ToPackage(ctx context.Context, pd *packages.PackageDescriptor, doer *user_m Name: pd.Package.Name, Version: pd.Version.Version, CreatedAt: pd.Version.CreatedUnix.AsTime(), - HTMLURL: pd.VersionHTMLURL(), + HTMLURL: pd.VersionHTMLURL(ctx), }, nil } diff --git a/services/convert/pull.go b/services/convert/pull.go index 4acbd880dc6..82ab0125d51 100644 --- a/services/convert/pull.go +++ b/services/convert/pull.go @@ -73,7 +73,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u apiPullRequest := &api.PullRequest{ ID: pr.ID, - URL: pr.Issue.HTMLURL(), + URL: pr.Issue.HTMLURL(ctx), Index: pr.Index, Poster: apiIssue.Poster, Title: apiIssue.Title, @@ -87,7 +87,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u IsLocked: apiIssue.IsLocked, Comments: apiIssue.Comments, ReviewComments: pr.GetReviewCommentsCount(ctx), - HTMLURL: pr.Issue.HTMLURL(), + HTMLURL: pr.Issue.HTMLURL(ctx), DiffURL: pr.Issue.DiffURL(), PatchURL: pr.Issue.PatchURL(), HasMerged: pr.HasMerged, @@ -348,7 +348,7 @@ func ToAPIPullRequests(ctx context.Context, baseRepo *repo_model.Repository, prs apiPullRequest := &api.PullRequest{ ID: pr.ID, - URL: pr.Issue.HTMLURL(), + URL: pr.Issue.HTMLURL(ctx), Index: pr.Index, Poster: apiIssue.Poster, Title: apiIssue.Title, @@ -362,7 +362,7 @@ func ToAPIPullRequests(ctx context.Context, baseRepo *repo_model.Repository, prs IsLocked: apiIssue.IsLocked, Comments: apiIssue.Comments, ReviewComments: reviewCounts[pr.IssueID], - HTMLURL: pr.Issue.HTMLURL(), + HTMLURL: pr.Issue.HTMLURL(ctx), DiffURL: pr.Issue.DiffURL(), PatchURL: pr.Issue.PatchURL(), HasMerged: pr.HasMerged, diff --git a/services/convert/pull_review.go b/services/convert/pull_review.go index 29a5ab7466b..574f34fa170 100644 --- a/services/convert/pull_review.go +++ b/services/convert/pull_review.go @@ -34,7 +34,7 @@ func ToPullReview(ctx context.Context, r *issues_model.Review, doer *user_model. Submitted: r.CreatedUnix.AsTime(), Updated: r.UpdatedUnix.AsTime(), HTMLURL: r.HTMLURL(ctx), - HTMLPullURL: r.Issue.HTMLURL(), + HTMLPullURL: r.Issue.HTMLURL(ctx), } if r.ReviewerTeam != nil { @@ -105,7 +105,7 @@ func ToPullReviewCommentList(ctx context.Context, review *issues_model.Review, d OrigCommitID: comment.OldRef, DiffHunk: patch2diff(comment.Patch), HTMLURL: comment.HTMLURL(ctx), - HTMLPullURL: review.Issue.HTMLURL(), + HTMLPullURL: review.Issue.HTMLURL(ctx), } if comment.Line < 0 { diff --git a/services/convert/pull_review_test.go b/services/convert/pull_review_test.go index d0a077ab247..c6e1165991e 100644 --- a/services/convert/pull_review_test.go +++ b/services/convert/pull_review_test.go @@ -6,7 +6,6 @@ package convert import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -25,27 +24,27 @@ func Test_ToPullReview(t *testing.T) { reviewList := []*issues_model.Review{review} t.Run("Anonymous User", func(t *testing.T) { - prList, err := ToPullReviewList(db.DefaultContext, reviewList, nil) + prList, err := ToPullReviewList(t.Context(), reviewList, nil) assert.NoError(t, err) assert.Empty(t, prList) }) t.Run("Reviewer Himself", func(t *testing.T) { - prList, err := ToPullReviewList(db.DefaultContext, reviewList, reviewer) + prList, err := ToPullReviewList(t.Context(), reviewList, reviewer) assert.NoError(t, err) assert.Len(t, prList, 1) }) t.Run("Other User", func(t *testing.T) { user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) - prList, err := ToPullReviewList(db.DefaultContext, reviewList, user4) + prList, err := ToPullReviewList(t.Context(), reviewList, user4) assert.NoError(t, err) assert.Empty(t, prList) }) t.Run("Admin User", func(t *testing.T) { adminUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - prList, err := ToPullReviewList(db.DefaultContext, reviewList, adminUser) + prList, err := ToPullReviewList(t.Context(), reviewList, adminUser) assert.NoError(t, err) assert.Len(t, prList, 1) }) diff --git a/services/convert/pull_test.go b/services/convert/pull_test.go index dfbe24d1846..dc8e4c637e0 100644 --- a/services/convert/pull_test.go +++ b/services/convert/pull_test.go @@ -6,13 +6,11 @@ package convert import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/structs" "github.com/stretchr/testify/assert" @@ -23,31 +21,31 @@ func TestPullRequest_APIFormat(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) headRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) - assert.NoError(t, pr.LoadIssue(db.DefaultContext)) - apiPullRequest := ToAPIPullRequest(git.DefaultContext, pr, nil) + assert.NoError(t, pr.LoadAttributes(t.Context())) + assert.NoError(t, pr.LoadIssue(t.Context())) + apiPullRequest := ToAPIPullRequest(t.Context(), pr, nil) assert.NotNil(t, apiPullRequest) assert.Equal(t, &structs.PRBranchInfo{ Name: "branch1", Ref: "refs/pull/2/head", Sha: "4a357436d925b5c974181ff12a994538ddc5a269", RepoID: 1, - Repository: ToRepo(db.DefaultContext, headRepo, access_model.Permission{AccessMode: perm.AccessModeRead}), + Repository: ToRepo(t.Context(), headRepo, access_model.Permission{AccessMode: perm.AccessModeRead}), }, apiPullRequest.Head) // withOut HeadRepo pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) - assert.NoError(t, pr.LoadIssue(db.DefaultContext)) - assert.NoError(t, pr.LoadAttributes(db.DefaultContext)) + assert.NoError(t, pr.LoadIssue(t.Context())) + assert.NoError(t, pr.LoadAttributes(t.Context())) // simulate fork deletion pr.HeadRepo = nil pr.HeadRepoID = 100000 - apiPullRequest = ToAPIPullRequest(git.DefaultContext, pr, nil) + apiPullRequest = ToAPIPullRequest(t.Context(), pr, nil) assert.NotNil(t, apiPullRequest) assert.Nil(t, apiPullRequest.Head.Repository) assert.EqualValues(t, -1, apiPullRequest.Head.RepoID) - apiPullRequests, err := ToAPIPullRequests(git.DefaultContext, pr.BaseRepo, []*issues_model.PullRequest{pr}, nil) + apiPullRequests, err := ToAPIPullRequests(t.Context(), pr.BaseRepo, []*issues_model.PullRequest{pr}, nil) assert.NoError(t, err) assert.Len(t, apiPullRequests, 1) assert.NotNil(t, apiPullRequests[0]) diff --git a/services/convert/release_test.go b/services/convert/release_test.go index bb618c9ca3f..a03a90abc7f 100644 --- a/services/convert/release_test.go +++ b/services/convert/release_test.go @@ -6,7 +6,6 @@ package convert import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -18,9 +17,9 @@ func TestRelease_ToRelease(t *testing.T) { repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) release1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{ID: 1}) - release1.LoadAttributes(db.DefaultContext) + release1.LoadAttributes(t.Context()) - apiRelease := ToAPIRelease(db.DefaultContext, repo1, release1) + apiRelease := ToAPIRelease(t.Context(), repo1, release1) assert.NotNil(t, apiRelease) assert.EqualValues(t, 1, apiRelease.ID) assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/releases/1", apiRelease.URL) diff --git a/services/convert/status.go b/services/convert/status.go index b4864a0307b..fe8240a8f72 100644 --- a/services/convert/status.go +++ b/services/convert/status.go @@ -42,20 +42,19 @@ func ToCommitStatuses(ctx context.Context, statuses []*git_model.CommitStatus) [ } // ToCombinedStatus converts List of CommitStatus to a CombinedStatus -func ToCombinedStatus(ctx context.Context, statuses []*git_model.CommitStatus, repo *api.Repository) *api.CombinedStatus { - if len(statuses) == 0 { - return nil +func ToCombinedStatus(ctx context.Context, commitID string, statuses []*git_model.CommitStatus, repo *api.Repository) *api.CombinedStatus { + status := api.CombinedStatus{ + SHA: commitID, + TotalCount: len(statuses), + Repository: repo, + CommitURL: repo.URL + "/commits/" + url.PathEscape(commitID), + URL: repo.URL + "/commits/" + url.PathEscape(commitID) + "/status", } combinedStatus := git_model.CalcCommitStatus(statuses) - - return &api.CombinedStatus{ - State: combinedStatus.State, - Statuses: ToCommitStatuses(ctx, statuses), - SHA: combinedStatus.SHA, - TotalCount: len(statuses), - Repository: repo, - CommitURL: repo.URL + "/commits/" + url.PathEscape(combinedStatus.SHA), - URL: repo.URL + "/commits/" + url.PathEscape(combinedStatus.SHA) + "/status", + if combinedStatus != nil { + status.Statuses = ToCommitStatuses(ctx, statuses) + status.State = combinedStatus.State } + return &status } diff --git a/services/convert/user.go b/services/convert/user.go index 90bcf35cf69..cee4de50912 100644 --- a/services/convert/user.go +++ b/services/convert/user.go @@ -53,7 +53,7 @@ func toUser(ctx context.Context, user *user_model.User, signed, authed bool) *ap FullName: user.FullName, Email: user.GetPlaceholderEmail(), AvatarURL: user.AvatarLink(ctx), - HTMLURL: user.HTMLURL(), + HTMLURL: user.HTMLURL(ctx), Created: user.CreatedUnix.AsTime(), Restricted: user.IsRestricted, Location: user.Location, diff --git a/services/convert/user_test.go b/services/convert/user_test.go index 199d500732a..d32cffb5124 100644 --- a/services/convert/user_test.go +++ b/services/convert/user_test.go @@ -6,7 +6,6 @@ package convert import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" api "code.gitea.io/gitea/modules/structs" @@ -19,22 +18,22 @@ func TestUser_ToUser(t *testing.T) { user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1, IsAdmin: true}) - apiUser := toUser(db.DefaultContext, user1, true, true) + apiUser := toUser(t.Context(), user1, true, true) assert.True(t, apiUser.IsAdmin) assert.Contains(t, apiUser.AvatarURL, "://") user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2, IsAdmin: false}) - apiUser = toUser(db.DefaultContext, user2, true, true) + apiUser = toUser(t.Context(), user2, true, true) assert.False(t, apiUser.IsAdmin) - apiUser = toUser(db.DefaultContext, user1, false, false) + apiUser = toUser(t.Context(), user1, false, false) assert.False(t, apiUser.IsAdmin) assert.Equal(t, api.VisibleTypePublic.String(), apiUser.Visibility) user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31, IsAdmin: false, Visibility: api.VisibleTypePrivate}) - apiUser = toUser(db.DefaultContext, user31, true, true) + apiUser = toUser(t.Context(), user31, true, true) assert.False(t, apiUser.IsAdmin) assert.Equal(t, api.VisibleTypePrivate.String(), apiUser.Visibility) } diff --git a/services/cron/tasks_extended.go b/services/cron/tasks_extended.go index 0018c5facc5..37471119842 100644 --- a/services/cron/tasks_extended.go +++ b/services/cron/tasks_extended.go @@ -171,34 +171,35 @@ func registerDeleteOldSystemNotices() { }) } +type GCLFSConfig struct { + BaseConfig + OlderThan time.Duration + LastUpdatedMoreThanAgo time.Duration + NumberToCheckPerRepo int64 + ProportionToCheckPerRepo float64 +} + func registerGCLFS() { if !setting.LFS.StartServer { return } - type GCLFSConfig struct { - OlderThanConfig - LastUpdatedMoreThanAgo time.Duration - NumberToCheckPerRepo int64 - ProportionToCheckPerRepo float64 - } RegisterTaskFatal("gc_lfs", &GCLFSConfig{ - OlderThanConfig: OlderThanConfig{ - BaseConfig: BaseConfig{ - Enabled: false, - RunAtStart: false, - Schedule: "@every 24h", - }, - // Only attempt to garbage collect lfs meta objects older than a week as the order of git lfs upload - // and git object upload is not necessarily guaranteed. It's possible to imagine a situation whereby - // an LFS object is uploaded but the git branch is not uploaded immediately, or there are some rapid - // changes in new branches that might lead to lfs objects becoming temporarily unassociated with git - // objects. - // - // It is likely that a week is potentially excessive but it should definitely be enough that any - // unassociated LFS object is genuinely unassociated. - OlderThan: 24 * time.Hour * 7, + BaseConfig: BaseConfig{ + Enabled: false, + RunAtStart: false, + Schedule: "@every 24h", }, + // Only attempt to garbage collect lfs meta objects older than a week as the order of git lfs upload + // and git object upload is not necessarily guaranteed. It's possible to imagine a situation whereby + // an LFS object is uploaded but the git branch is not uploaded immediately, or there are some rapid + // changes in new branches that might lead to lfs objects becoming temporarily unassociated with git + // objects. + // + // It is likely that a week is potentially excessive but it should definitely be enough that any + // unassociated LFS object is genuinely unassociated. + OlderThan: 24 * time.Hour * 7, + // Only GC things that haven't been looked at in the past 3 days LastUpdatedMoreThanAgo: 24 * time.Hour * 3, NumberToCheckPerRepo: 100, diff --git a/services/cron/tasks_extended_test.go b/services/cron/tasks_extended_test.go new file mode 100644 index 00000000000..a3d40630a3c --- /dev/null +++ b/services/cron/tasks_extended_test.go @@ -0,0 +1,51 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package cron + +import ( + "testing" + "time" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + + "github.com/stretchr/testify/assert" +) + +func Test_GCLFSConfig(t *testing.T) { + cfg, err := setting.NewConfigProviderFromData(` +[cron.gc_lfs] +ENABLED = true +RUN_AT_START = true +SCHEDULE = "@every 2h" +OLDER_THAN = "1h" +LAST_UPDATED_MORE_THAN_AGO = "7h" +NUMBER_TO_CHECK_PER_REPO = 10 +PROPORTION_TO_CHECK_PER_REPO = 0.1 +`) + assert.NoError(t, err) + defer test.MockVariableValue(&setting.CfgProvider, cfg)() + + config := &GCLFSConfig{ + BaseConfig: BaseConfig{ + Enabled: false, + RunAtStart: false, + Schedule: "@every 24h", + }, + OlderThan: 24 * time.Hour * 7, + LastUpdatedMoreThanAgo: 24 * time.Hour * 3, + NumberToCheckPerRepo: 100, + ProportionToCheckPerRepo: 0.6, + } + + _, err = setting.GetCronSettings("gc_lfs", config) + assert.NoError(t, err) + assert.True(t, config.Enabled) + assert.True(t, config.RunAtStart) + assert.Equal(t, "@every 2h", config.Schedule) + assert.Equal(t, 1*time.Hour, config.OlderThan) + assert.Equal(t, 7*time.Hour, config.LastUpdatedMoreThanAgo) + assert.Equal(t, int64(10), config.NumberToCheckPerRepo) + assert.InDelta(t, 0.1, config.ProportionToCheckPerRepo, 0.001) +} diff --git a/services/doctor/dbconsistency_test.go b/services/doctor/dbconsistency_test.go index eb427dee737..d2cf2c47254 100644 --- a/services/doctor/dbconsistency_test.go +++ b/services/doctor/dbconsistency_test.go @@ -24,16 +24,16 @@ func TestConsistencyCheck(t *testing.T) { }) require.NotEqual(t, -1, idx) - _ = db.TruncateBeans(db.DefaultContext, &auth.OAuth2Application{}, &user.User{}) - _ = db.TruncateBeans(db.DefaultContext, &auth.OAuth2Application{}, &auth.OAuth2Application{}) + _ = db.TruncateBeans(t.Context(), &auth.OAuth2Application{}, &user.User{}) + _ = db.TruncateBeans(t.Context(), &auth.OAuth2Application{}, &auth.OAuth2Application{}) - err := db.Insert(db.DefaultContext, &user.User{ID: 1}) + err := db.Insert(t.Context(), &user.User{ID: 1}) assert.NoError(t, err) - err = db.Insert(db.DefaultContext, &auth.OAuth2Application{Name: "test-oauth2-app-1", ClientID: "client-id-1"}) + err = db.Insert(t.Context(), &auth.OAuth2Application{Name: "test-oauth2-app-1", ClientID: "client-id-1"}) assert.NoError(t, err) - err = db.Insert(db.DefaultContext, &auth.OAuth2Application{Name: "test-oauth2-app-2", ClientID: "client-id-2", UID: 1}) + err = db.Insert(t.Context(), &auth.OAuth2Application{Name: "test-oauth2-app-2", ClientID: "client-id-2", UID: 1}) assert.NoError(t, err) - err = db.Insert(db.DefaultContext, &auth.OAuth2Application{Name: "test-oauth2-app-3", ClientID: "client-id-3", UID: 99999999}) + err = db.Insert(t.Context(), &auth.OAuth2Application{Name: "test-oauth2-app-3", ClientID: "client-id-3", UID: 99999999}) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-1"}) @@ -41,7 +41,7 @@ func TestConsistencyCheck(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-3"}) oauth2AppCheck := checks[idx] - err = oauth2AppCheck.Run(db.DefaultContext, log.GetManager().GetLogger(log.DEFAULT), true) + err = oauth2AppCheck.Run(t.Context(), log.GetManager().GetLogger(log.DEFAULT), true) assert.NoError(t, err) unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ClientID: "client-id-1"}) diff --git a/services/doctor/doctor.go b/services/doctor/doctor.go index c6810a5fa07..e7fe29d8ee4 100644 --- a/services/doctor/doctor.go +++ b/services/doctor/doctor.go @@ -36,7 +36,7 @@ func initDBSkipLogger(ctx context.Context) error { return fmt.Errorf("db.InitEngine: %w", err) } // some doctor sub-commands need to use git command - if err := git.InitFull(ctx); err != nil { + if err := git.InitFull(); err != nil { return fmt.Errorf("git.InitFull: %w", err) } return nil diff --git a/services/feed/feed_test.go b/services/feed/feed_test.go index 705d42a2eb8..136344cd289 100644 --- a/services/feed/feed_test.go +++ b/services/feed/feed_test.go @@ -20,7 +20,7 @@ func TestGetFeeds(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - actions, count, err := GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err := GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedUser: user, Actor: user, IncludePrivate: true, @@ -34,7 +34,7 @@ func TestGetFeeds(t *testing.T) { } assert.Equal(t, int64(1), count) - actions, count, err = GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err = GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedUser: user, Actor: user, IncludePrivate: false, @@ -52,7 +52,7 @@ func TestGetFeedsForRepos(t *testing.T) { pubRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 8}) // private repo & no login - actions, count, err := GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err := GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedRepo: privRepo, IncludePrivate: true, }) @@ -61,7 +61,7 @@ func TestGetFeedsForRepos(t *testing.T) { assert.Equal(t, int64(0), count) // public repo & no login - actions, count, err = GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err = GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedRepo: pubRepo, IncludePrivate: true, }) @@ -70,7 +70,7 @@ func TestGetFeedsForRepos(t *testing.T) { assert.Equal(t, int64(1), count) // private repo and login - actions, count, err = GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err = GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedRepo: privRepo, IncludePrivate: true, Actor: user, @@ -80,7 +80,7 @@ func TestGetFeedsForRepos(t *testing.T) { assert.Equal(t, int64(1), count) // public repo & login - actions, count, err = GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err = GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedRepo: pubRepo, IncludePrivate: true, Actor: user, @@ -96,7 +96,7 @@ func TestGetFeeds2(t *testing.T) { org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - actions, count, err := GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err := GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedUser: org, Actor: user, IncludePrivate: true, @@ -111,7 +111,7 @@ func TestGetFeeds2(t *testing.T) { } assert.Equal(t, int64(1), count) - actions, count, err = GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err = GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedUser: org, Actor: user, IncludePrivate: false, @@ -133,7 +133,7 @@ func TestGetFeedsCorrupted(t *testing.T) { RepoID: 1700, }) - actions, count, err := GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, count, err := GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedUser: user, Actor: user, IncludePrivate: true, @@ -146,18 +146,18 @@ func TestGetFeedsCorrupted(t *testing.T) { func TestRepoActions(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - _ = db.TruncateBeans(db.DefaultContext, &activities_model.Action{}) + _ = db.TruncateBeans(t.Context(), &activities_model.Action{}) for i := range 3 { - _ = db.Insert(db.DefaultContext, &activities_model.Action{ + _ = db.Insert(t.Context(), &activities_model.Action{ UserID: 2 + int64(i), ActUserID: 2, RepoID: repo.ID, OpType: activities_model.ActionCommentIssue, }) } - count, _ := db.Count[activities_model.Action](db.DefaultContext, &db.ListOptions{}) + count, _ := db.Count[activities_model.Action](t.Context(), &db.ListOptions{}) assert.EqualValues(t, 3, count) - actions, _, err := GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{ + actions, _, err := GetFeeds(t.Context(), activities_model.GetFeedsOptions{ RequestedRepo: repo, }) assert.NoError(t, err) @@ -172,7 +172,7 @@ func TestNotifyWatchers(t *testing.T) { RepoID: 1, OpType: activities_model.ActionStarRepo, } - assert.NoError(t, NotifyWatchers(db.DefaultContext, action)) + assert.NoError(t, NotifyWatchers(t.Context(), action)) // One watchers are inactive, thus action is only created for user 8, 1, 4, 11 unittest.AssertExistsAndLoadBean(t, &activities_model.Action{ diff --git a/services/feed/notifier_test.go b/services/feed/notifier_test.go index 60cf7fbb49d..ef70facd1e4 100644 --- a/services/feed/notifier_test.go +++ b/services/feed/notifier_test.go @@ -8,7 +8,6 @@ import ( "testing" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -46,7 +45,7 @@ func TestRenameRepoAction(t *testing.T) { } unittest.AssertNotExistsBean(t, actionBean) - NewNotifier().RenameRepository(db.DefaultContext, user, repo, oldRepoName) + NewNotifier().RenameRepository(t.Context(), user, repo, oldRepoName) unittest.AssertExistsAndLoadBean(t, actionBean) unittest.CheckConsistencyFor(t, &activities_model.Action{}) diff --git a/services/forms/org.go b/services/forms/org.go index 2ac18ef25cc..3997e1da845 100644 --- a/services/forms/org.go +++ b/services/forms/org.go @@ -41,7 +41,6 @@ type UpdateOrgSettingForm struct { Description string `binding:"MaxSize(255)"` Website string `binding:"ValidUrl;MaxSize(255)"` Location string `binding:"MaxSize(50)"` - Visibility structs.VisibleType MaxRepoCreation int RepoAdminChangeTeamAccess bool } diff --git a/services/gitdiff/csv_test.go b/services/gitdiff/csv_test.go index f91e0e9aa72..b45433d8c24 100644 --- a/services/gitdiff/csv_test.go +++ b/services/gitdiff/csv_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" csv_module "code.gitea.io/gitea/modules/csv" "code.gitea.io/gitea/modules/setting" @@ -191,7 +190,7 @@ c,d,e`, } for n, c := range cases { - diff, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(c.diff), "") + diff, err := ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(c.diff), "") assert.NoError(t, err) var baseReader *csv.Reader diff --git a/services/gitdiff/git_diff_tree_test.go b/services/gitdiff/git_diff_tree_test.go index 313d279e95f..c6e3fbab813 100644 --- a/services/gitdiff/git_diff_tree_test.go +++ b/services/gitdiff/git_diff_tree_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/git" "github.com/stretchr/testify/assert" @@ -206,11 +205,11 @@ func TestGitDiffTree(t *testing.T) { for _, tt := range test { t.Run(tt.Name, func(t *testing.T) { - gitRepo, err := git.OpenRepository(git.DefaultContext, tt.RepoPath) + gitRepo, err := git.OpenRepository(t.Context(), tt.RepoPath) assert.NoError(t, err) defer gitRepo.Close() - diffPaths, err := GetDiffTree(db.DefaultContext, gitRepo, tt.useMergeBase, tt.BaseSha, tt.HeadSha) + diffPaths, err := GetDiffTree(t.Context(), gitRepo, tt.useMergeBase, tt.BaseSha, tt.HeadSha) require.NoError(t, err) assert.Equal(t, tt.Expected, diffPaths) @@ -415,11 +414,11 @@ func TestGitDiffTreeErrors(t *testing.T) { for _, tt := range test { t.Run(tt.Name, func(t *testing.T) { - gitRepo, err := git.OpenRepository(git.DefaultContext, tt.RepoPath) + gitRepo, err := git.OpenRepository(t.Context(), tt.RepoPath) assert.NoError(t, err) defer gitRepo.Close() - diffPaths, err := GetDiffTree(db.DefaultContext, gitRepo, true, tt.BaseSha, tt.HeadSha) + diffPaths, err := GetDiffTree(t.Context(), gitRepo, true, tt.BaseSha, tt.HeadSha) assert.Error(t, err) assert.Nil(t, diffPaths) }) diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index b84530043a1..83815caeb56 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -9,7 +9,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -158,7 +157,7 @@ diff --git "\\a/README.md" "\\b/README.md" } for _, testcase := range tests { t.Run(testcase.name, func(t *testing.T) { - got, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), testcase.skipTo) + got, err := ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), testcase.skipTo) if (err != nil) != testcase.wantErr { t.Errorf("ParsePatch(%q) error = %v, wantErr %v", testcase.name, err, testcase.wantErr) return @@ -377,7 +376,7 @@ index 6961180..9ba1a00 100644 for _, testcase := range tests { t.Run(testcase.name, func(t *testing.T) { - got, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") + got, err := ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") if (err != nil) != testcase.wantErr { t.Errorf("ParsePatch(%q) error = %v, wantErr %v", testcase.name, err, testcase.wantErr) return @@ -420,21 +419,21 @@ index 0000000..6bb8f39 diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n") } diff = diffBuilder.String() - result, err := ParsePatch(db.DefaultContext, 20, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err := ParsePatch(t.Context(), 20, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } if !result.Files[0].IsIncomplete { t.Errorf("Files should be incomplete! %v", result.Files[0]) } - result, err = ParsePatch(db.DefaultContext, 40, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(t.Context(), 40, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } if result.Files[0].IsIncomplete { t.Errorf("Files should not be incomplete! %v", result.Files[0]) } - result, err = ParsePatch(db.DefaultContext, 40, 5, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(t.Context(), 40, 5, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } @@ -465,14 +464,14 @@ index 0000000..6bb8f39 diffBuilder.WriteString("+line" + strconv.Itoa(35) + "\n") diff = diffBuilder.String() - result, err = ParsePatch(db.DefaultContext, 20, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(t.Context(), 20, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } if !result.Files[0].IsIncomplete { t.Errorf("Files should be incomplete! %v", result.Files[0]) } - result, err = ParsePatch(db.DefaultContext, 40, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(t.Context(), 40, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } @@ -491,7 +490,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + _, err = ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -507,7 +506,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2), "") + _, err = ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -523,7 +522,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a), "") + _, err = ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -539,7 +538,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff3), "") + _, err = ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff3), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -571,7 +570,7 @@ func TestDiff_LoadCommentsNoOutdated(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) diff := setupDefaultDiff() - assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, false)) + assert.NoError(t, diff.LoadComments(t.Context(), issue, user, false)) assert.Len(t, diff.Files[0].Sections[0].Lines[0].Comments, 2) } @@ -581,7 +580,7 @@ func TestDiff_LoadCommentsWithOutdated(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) diff := setupDefaultDiff() - assert.NoError(t, diff.LoadComments(db.DefaultContext, issue, user, true)) + assert.NoError(t, diff.LoadComments(t.Context(), issue, user, true)) assert.Len(t, diff.Files[0].Sections[0].Lines[0].Comments, 3) } @@ -637,6 +636,6 @@ func TestNoCrashes(t *testing.T) { } for _, testcase := range tests { // It shouldn't crash, so don't care about the output. - ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") + ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") } } diff --git a/services/gitdiff/submodule_test.go b/services/gitdiff/submodule_test.go index c793969f0e6..9f2cf1d1c60 100644 --- a/services/gitdiff/submodule_test.go +++ b/services/gitdiff/submodule_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" @@ -204,7 +203,7 @@ index 0000000..68972a9 for _, testcase := range tests { t.Run(testcase.name, func(t *testing.T) { - diff, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") + diff, err := ParsePatch(t.Context(), setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") assert.NoError(t, err) for i, expected := range testcase.infos { diff --git a/services/issue/assignee_test.go b/services/issue/assignee_test.go index 38d56f9d9dc..4bf0884f521 100644 --- a/services/issue/assignee_test.go +++ b/services/issue/assignee_test.go @@ -6,7 +6,6 @@ package issue import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -18,30 +17,30 @@ func TestDeleteNotPassedAssignee(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // Fake issue with assignees - issue, err := issues_model.GetIssueByID(db.DefaultContext, 1) + issue, err := issues_model.GetIssueByID(t.Context(), 1) assert.NoError(t, err) - err = issue.LoadAttributes(db.DefaultContext) + err = issue.LoadAttributes(t.Context()) assert.NoError(t, err) assert.Len(t, issue.Assignees, 1) - user1, err := user_model.GetUserByID(db.DefaultContext, 1) // This user is already assigned (see the definition in fixtures), so running UpdateAssignee should unassign him + user1, err := user_model.GetUserByID(t.Context(), 1) // This user is already assigned (see the definition in fixtures), so running UpdateAssignee should unassign him assert.NoError(t, err) // Check if he got removed - isAssigned, err := issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, user1) + isAssigned, err := issues_model.IsUserAssignedToIssue(t.Context(), issue, user1) assert.NoError(t, err) assert.True(t, isAssigned) // Clean everyone - err = DeleteNotPassedAssignee(db.DefaultContext, issue, user1, []*user_model.User{}) + err = DeleteNotPassedAssignee(t.Context(), issue, user1, []*user_model.User{}) assert.NoError(t, err) assert.Empty(t, issue.Assignees) // Reload to check they're gone issue.ResetAttributesLoaded() - assert.NoError(t, issue.LoadAssignees(db.DefaultContext)) + assert.NoError(t, issue.LoadAssignees(t.Context())) assert.Empty(t, issue.Assignees) assert.Empty(t, issue.Assignee) } diff --git a/services/issue/comments.go b/services/issue/comments.go index 74159992f4d..1d2ffc7794f 100644 --- a/services/issue/comments.go +++ b/services/issue/comments.go @@ -80,6 +80,12 @@ func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_m return nil, err } + // reload issue to ensure it has the latest data, especially the number of comments + issue, err = issues_model.GetIssueByID(ctx, issue.ID) + if err != nil { + return nil, err + } + notify_service.CreateIssueComment(ctx, doer, repo, issue, comment, mentions) return comment, nil diff --git a/services/issue/comments_test.go b/services/issue/comments_test.go index 771a070330d..df66389e4a1 100644 --- a/services/issue/comments_test.go +++ b/services/issue/comments_test.go @@ -6,7 +6,6 @@ package issue import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -23,7 +22,7 @@ func Test_DeleteCommentWithReview(t *testing.T) { user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) // since this is the last comment of the review, it should be deleted when the comment is deleted - deletedReviewComment, err := DeleteComment(db.DefaultContext, user1, comment) + deletedReviewComment, err := DeleteComment(t.Context(), user1, comment) assert.NoError(t, err) assert.NotNil(t, deletedReviewComment) diff --git a/services/issue/commit_test.go b/services/issue/commit_test.go index 05188036836..d19702269a9 100644 --- a/services/issue/commit_test.go +++ b/services/issue/commit_test.go @@ -7,7 +7,6 @@ import ( "testing" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -61,7 +60,7 @@ func TestUpdateIssuesCommit(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 2}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -88,7 +87,7 @@ func TestUpdateIssuesCommit(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 1}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, "non-existing-branch")) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, "non-existing-branch")) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -114,7 +113,7 @@ func TestUpdateIssuesCommit(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 1}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -140,7 +139,7 @@ func TestUpdateIssuesCommit_Colon(t *testing.T) { issueBean := &issues_model.Issue{RepoID: repo.ID, Index: 4} unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 2}, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) } @@ -173,7 +172,7 @@ func TestUpdateIssuesCommit_Issue5957(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, "non-existing-branch")) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, "non-existing-branch")) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -208,7 +207,7 @@ func TestUpdateIssuesCommit_AnotherRepo(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -243,7 +242,7 @@ func TestUpdateIssuesCommit_AnotherRepo_FullAddress(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertExistsAndLoadBean(t, commentBean) unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1") unittest.CheckConsistencyFor(t, &activities_model.Action{}) @@ -293,7 +292,7 @@ func TestUpdateIssuesCommit_AnotherRepoNoPermission(t *testing.T) { unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, commentBean2) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") - assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch)) + assert.NoError(t, UpdateIssuesCommit(t.Context(), user, repo, pushCommits, repo.DefaultBranch)) unittest.AssertNotExistsBean(t, commentBean) unittest.AssertNotExistsBean(t, commentBean2) unittest.AssertNotExistsBean(t, issueBean, "is_closed=1") diff --git a/services/issue/issue_test.go b/services/issue/issue_test.go index bad0d65d1ed..61ed13ed2fc 100644 --- a/services/issue/issue_test.go +++ b/services/issue/issue_test.go @@ -6,7 +6,6 @@ package issue import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -35,7 +34,7 @@ func TestGetRefEndNamesAndURLs(t *testing.T) { func TestIssue_DeleteIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - issueIDs, err := issues_model.GetIssueIDsByRepoID(db.DefaultContext, 1) + issueIDs, err := issues_model.GetIssueIDsByRepoID(t.Context(), 1) assert.NoError(t, err) assert.Len(t, issueIDs, 5) @@ -44,43 +43,43 @@ func TestIssue_DeleteIssue(t *testing.T) { ID: issueIDs[2], } - _, err = deleteIssue(db.DefaultContext, issue) + _, err = deleteIssue(t.Context(), issue) assert.NoError(t, err) - issueIDs, err = issues_model.GetIssueIDsByRepoID(db.DefaultContext, 1) + issueIDs, err = issues_model.GetIssueIDsByRepoID(t.Context(), 1) assert.NoError(t, err) assert.Len(t, issueIDs, 4) // check attachment removal - attachments, err := repo_model.GetAttachmentsByIssueID(db.DefaultContext, 4) + attachments, err := repo_model.GetAttachmentsByIssueID(t.Context(), 4) assert.NoError(t, err) - issue, err = issues_model.GetIssueByID(db.DefaultContext, 4) + issue, err = issues_model.GetIssueByID(t.Context(), 4) assert.NoError(t, err) - _, err = deleteIssue(db.DefaultContext, issue) + _, err = deleteIssue(t.Context(), issue) assert.NoError(t, err) assert.Len(t, attachments, 2) for i := range attachments { - attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, attachments[i].UUID) + attachment, err := repo_model.GetAttachmentByUUID(t.Context(), attachments[i].UUID) assert.Error(t, err) assert.True(t, repo_model.IsErrAttachmentNotExist(err)) assert.Nil(t, attachment) } // check issue dependencies - user, err := user_model.GetUserByID(db.DefaultContext, 1) + user, err := user_model.GetUserByID(t.Context(), 1) assert.NoError(t, err) - issue1, err := issues_model.GetIssueByID(db.DefaultContext, 1) + issue1, err := issues_model.GetIssueByID(t.Context(), 1) assert.NoError(t, err) - issue2, err := issues_model.GetIssueByID(db.DefaultContext, 2) + issue2, err := issues_model.GetIssueByID(t.Context(), 2) assert.NoError(t, err) - err = issues_model.CreateIssueDependency(db.DefaultContext, user, issue1, issue2) + err = issues_model.CreateIssueDependency(t.Context(), user, issue1, issue2) assert.NoError(t, err) - left, err := issues_model.IssueNoDependenciesLeft(db.DefaultContext, issue1) + left, err := issues_model.IssueNoDependenciesLeft(t.Context(), issue1) assert.NoError(t, err) assert.False(t, left) - _, err = deleteIssue(db.DefaultContext, issue2) + _, err = deleteIssue(t.Context(), issue2) assert.NoError(t, err) - left, err = issues_model.IssueNoDependenciesLeft(db.DefaultContext, issue1) + left, err = issues_model.IssueNoDependenciesLeft(t.Context(), issue1) assert.NoError(t, err) assert.True(t, left) } diff --git a/services/issue/label_test.go b/services/issue/label_test.go index 90608c9e269..093b16b53fe 100644 --- a/services/issue/label_test.go +++ b/services/issue/label_test.go @@ -6,7 +6,6 @@ package issue import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -33,7 +32,7 @@ func TestIssue_AddLabels(t *testing.T) { labels[i] = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: labelID}) } doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: test.doerID}) - assert.NoError(t, AddLabels(db.DefaultContext, issue, doer, labels)) + assert.NoError(t, AddLabels(t.Context(), issue, doer, labels)) for _, labelID := range test.labelIDs { unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: test.issueID, LabelID: labelID}) } @@ -56,7 +55,7 @@ func TestIssue_AddLabel(t *testing.T) { issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: test.issueID}) label := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: test.labelID}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: test.doerID}) - assert.NoError(t, AddLabel(db.DefaultContext, issue, doer, label)) + assert.NoError(t, AddLabel(t.Context(), issue, doer, label)) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: test.issueID, LabelID: test.labelID}) } } diff --git a/services/issue/milestone_test.go b/services/issue/milestone_test.go index bf5abc85b70..2ef482e23c2 100644 --- a/services/issue/milestone_test.go +++ b/services/issue/milestone_test.go @@ -6,7 +6,6 @@ package issue import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -23,8 +22,8 @@ func TestChangeMilestoneAssign(t *testing.T) { oldMilestoneID := issue.MilestoneID issue.MilestoneID = 2 - assert.NoError(t, issue.LoadMilestone(db.DefaultContext)) - assert.NoError(t, ChangeMilestoneAssign(db.DefaultContext, issue, doer, oldMilestoneID)) + assert.NoError(t, issue.LoadMilestone(t.Context())) + assert.NoError(t, ChangeMilestoneAssign(t.Context(), issue, doer, oldMilestoneID)) unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ IssueID: issue.ID, Type: issues_model.CommentTypeMilestone, @@ -36,7 +35,7 @@ func TestChangeMilestoneAssign(t *testing.T) { oldMilestoneID = issue.MilestoneID issue.MilestoneID = 0 - assert.NoError(t, ChangeMilestoneAssign(db.DefaultContext, issue, doer, oldMilestoneID)) + assert.NoError(t, ChangeMilestoneAssign(t.Context(), issue, doer, oldMilestoneID)) assert.EqualValues(t, 0, issue.MilestoneID) assert.Nil(t, issue.Milestone) } diff --git a/services/issue/reaction_test.go b/services/issue/reaction_test.go index 7734860fc0d..bf2e554d418 100644 --- a/services/issue/reaction_test.go +++ b/services/issue/reaction_test.go @@ -6,7 +6,6 @@ package issue import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -20,9 +19,9 @@ func addReaction(t *testing.T, doer *user_model.User, issue *issues_model.Issue, var reaction *issues_model.Reaction var err error if comment == nil { - reaction, err = CreateIssueReaction(db.DefaultContext, doer, issue, content) + reaction, err = CreateIssueReaction(t.Context(), doer, issue, content) } else { - reaction, err = CreateCommentReaction(db.DefaultContext, doer, comment, content) + reaction, err = CreateCommentReaction(t.Context(), doer, comment, content) } assert.NoError(t, err) assert.NotNil(t, reaction) @@ -47,7 +46,7 @@ func TestIssueAddDuplicateReaction(t *testing.T) { addReaction(t, user1, issue, nil, "heart") - reaction, err := CreateIssueReaction(db.DefaultContext, user1, issue, "heart") + reaction, err := CreateIssueReaction(t.Context(), user1, issue, "heart") assert.Error(t, err) assert.Equal(t, issues_model.ErrReactionAlreadyExist{Reaction: "heart"}, err) @@ -63,7 +62,7 @@ func TestIssueDeleteReaction(t *testing.T) { addReaction(t, user1, issue, nil, "heart") - err := issues_model.DeleteIssueReaction(db.DefaultContext, user1.ID, issue.ID, "heart") + err := issues_model.DeleteIssueReaction(t.Context(), user1.ID, issue.ID, "heart") assert.NoError(t, err) unittest.AssertNotExistsBean(t, &issues_model.Reaction{Type: "heart", UserID: user1.ID, IssueID: issue.ID}) @@ -91,12 +90,12 @@ func TestIssueReactionCount(t *testing.T) { addReaction(t, user4, issue, nil, "heart") addReaction(t, ghost, issue, nil, "-1") - reactionsList, _, err := issues_model.FindReactions(db.DefaultContext, issues_model.FindReactionsOptions{ + reactionsList, _, err := issues_model.FindReactions(t.Context(), issues_model.FindReactionsOptions{ IssueID: issue.ID, }) assert.NoError(t, err) assert.Len(t, reactionsList, 7) - _, err = reactionsList.LoadUsers(db.DefaultContext, repo) + _, err = reactionsList.LoadUsers(t.Context(), repo) assert.NoError(t, err) reactions := reactionsList.GroupByType() @@ -137,7 +136,7 @@ func TestIssueCommentDeleteReaction(t *testing.T) { addReaction(t, org3, nil, comment, "heart") addReaction(t, user4, nil, comment, "+1") - reactionsList, _, err := issues_model.FindReactions(db.DefaultContext, issues_model.FindReactionsOptions{ + reactionsList, _, err := issues_model.FindReactions(t.Context(), issues_model.FindReactionsOptions{ IssueID: comment.IssueID, CommentID: comment.ID, }) @@ -156,7 +155,7 @@ func TestIssueCommentReactionCount(t *testing.T) { comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 1}) addReaction(t, user1, nil, comment, "heart") - assert.NoError(t, issues_model.DeleteCommentReaction(db.DefaultContext, user1.ID, comment.IssueID, comment.ID, "heart")) + assert.NoError(t, issues_model.DeleteCommentReaction(t.Context(), user1.ID, comment.IssueID, comment.ID, "heart")) unittest.AssertNotExistsBean(t, &issues_model.Reaction{Type: "heart", UserID: user1.ID, IssueID: comment.IssueID, CommentID: comment.ID}) } diff --git a/services/issue/suggestion_test.go b/services/issue/suggestion_test.go index a5b39d27bb8..9b23e5aca33 100644 --- a/services/issue/suggestion_test.go +++ b/services/issue/suggestion_test.go @@ -6,7 +6,6 @@ package issue import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/optional" @@ -44,7 +43,7 @@ func Test_Suggestion(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.keyword, func(t *testing.T) { - issues, err := GetSuggestion(db.DefaultContext, repo1, testCase.isPull, testCase.keyword) + issues, err := GetSuggestion(t.Context(), repo1, testCase.isPull, testCase.keyword) assert.NoError(t, err) issueIndexes := make([]int64, 0, len(issues)) diff --git a/services/lfs/server.go b/services/lfs/server.go index c9d9f164bf3..9f2e532f23a 100644 --- a/services/lfs/server.go +++ b/services/lfs/server.go @@ -114,7 +114,7 @@ func DownloadHandler(ctx *context.Context) { } } - ctx.Resp.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", fromByte, toByte, meta.Size-fromByte)) + ctx.Resp.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", fromByte, toByte, meta.Size)) ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Range") } } diff --git a/services/mailer/mail_issue_common.go b/services/mailer/mail_issue_common.go index a34d8a68c97..f5190ce8a15 100644 --- a/services/mailer/mail_issue_common.go +++ b/services/mailer/mail_issue_common.go @@ -56,9 +56,9 @@ func composeIssueCommentMessages(ctx context.Context, comment *mailComment, lang commentType := issues_model.CommentTypeComment if comment.Comment != nil { commentType = comment.Comment.Type - link = comment.Issue.HTMLURL() + "#" + comment.Comment.HashTag() + link = comment.Issue.HTMLURL(ctx) + "#" + comment.Comment.HashTag() } else { - link = comment.Issue.HTMLURL() + link = comment.Issue.HTMLURL(ctx) } reviewType := issues_model.ReviewTypeComment @@ -175,7 +175,7 @@ func composeIssueCommentMessages(ctx context.Context, comment *mailComment, lang msg.SetHeader("In-Reply-To", reference) references := []string{reference} - listUnsubscribe := []string{"<" + comment.Issue.HTMLURL() + ">"} + listUnsubscribe := []string{"<" + comment.Issue.HTMLURL(ctx) + ">"} if setting.IncomingEmail.Enabled { if replyPayload != nil { @@ -313,7 +313,7 @@ func generateAdditionalHeadersForIssue(ctx *mailComment, reason string, recipien maps.Copy(headers, generateReasonHeaders(reason)) headers["X-Gitea-Issue-ID"] = issueID - headers["X-Gitea-Issue-Link"] = ctx.Issue.HTMLURL() + headers["X-Gitea-Issue-Link"] = ctx.Issue.HTMLURL(context.TODO()) // FIXME: use proper context headers["X-GitLab-Issue-IID"] = issueID return headers diff --git a/services/mailer/mail_test.go b/services/mailer/mail_test.go index 24f5d39d50d..da278ba36b3 100644 --- a/services/mailer/mail_test.go +++ b/services/mailer/mail_test.go @@ -18,7 +18,6 @@ import ( actions_model "code.gitea.io/gitea/models/actions" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -68,7 +67,7 @@ func prepareMailerTest(t *testing.T) (doer *user_model.User, repo *repo_model.Re repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, Owner: doer}) issue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1, Repo: repo, Poster: doer}) comment = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: 2, Issue: issue}) - require.NoError(t, issue.LoadRepo(db.DefaultContext)) + require.NoError(t, issue.LoadRepo(t.Context())) return doer, repo, issue, comment } @@ -150,12 +149,12 @@ func TestComposeIssueComment(t *testing.T) { assert.NoError(t, err) // text/plain - assert.Contains(t, string(b), fmt.Sprintf(`( %s )`, doer.HTMLURL())) - assert.Contains(t, string(b), fmt.Sprintf(`( %s )`, issue.HTMLURL())) + assert.Contains(t, string(b), fmt.Sprintf(`( %s )`, doer.HTMLURL(t.Context()))) + assert.Contains(t, string(b), fmt.Sprintf(`( %s )`, issue.HTMLURL(t.Context()))) // text/html - assert.Contains(t, string(b), fmt.Sprintf(`href="%s"`, doer.HTMLURL())) - assert.Contains(t, string(b), fmt.Sprintf(`href="%s"`, issue.HTMLURL())) + assert.Contains(t, string(b), fmt.Sprintf(`href="%s"`, doer.HTMLURL(t.Context()))) + assert.Contains(t, string(b), fmt.Sprintf(`href="%s"`, issue.HTMLURL(t.Context()))) } func TestMailMentionsComment(t *testing.T) { @@ -252,7 +251,7 @@ func TestTemplateSelection(t *testing.T) { func TestTemplateServices(t *testing.T) { doer, _, issue, comment := prepareMailerTest(t) - assert.NoError(t, issue.LoadRepo(db.DefaultContext)) + assert.NoError(t, issue.LoadRepo(t.Context())) expect := func(t *testing.T, issue *issues_model.Issue, comment *issues_model.Comment, doer *user_model.User, actionType activities_model.ActionType, fromMention bool, tplSubject, tplBody, expSubject, expBody string, @@ -447,7 +446,7 @@ func TestGenerateMessageIDForActionsWorkflowRunStatusEmail(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 795, RepoID: repo.ID}) - assert.NoError(t, run.LoadAttributes(db.DefaultContext)) + assert.NoError(t, run.LoadAttributes(t.Context())) msgID := generateMessageIDForActionsWorkflowRunStatusEmail(repo, run) assert.Equal(t, "", msgID) } diff --git a/services/mailer/mail_workflow_run.go b/services/mailer/mail_workflow_run.go index 29b3abda8ee..62e85521591 100644 --- a/services/mailer/mail_workflow_run.go +++ b/services/mailer/mail_workflow_run.go @@ -33,7 +33,18 @@ func generateMessageIDForActionsWorkflowRunStatusEmail(repo *repo_model.Reposito return fmt.Sprintf("<%s/actions/runs/%d@%s>", repo.FullName(), run.Index, setting.Domain) } -func composeAndSendActionsWorkflowRunStatusEmail(ctx context.Context, repo *repo_model.Repository, run *actions_model.ActionRun, sender *user_model.User, recipients []*user_model.User) { +func composeAndSendActionsWorkflowRunStatusEmail(ctx context.Context, repo *repo_model.Repository, run *actions_model.ActionRun, sender *user_model.User, recipients []*user_model.User) error { + jobs, err := actions_model.GetRunJobsByRunID(ctx, run.ID) + if err != nil { + return err + } + for _, job := range jobs { + if !job.Status.IsDone() { + log.Debug("composeAndSendActionsWorkflowRunStatusEmail: A job is not done. Will not compose and send actions email.") + return nil + } + } + subject := "Run" switch run.Status { case actions_model.StatusFailure: @@ -48,11 +59,6 @@ func composeAndSendActionsWorkflowRunStatusEmail(ctx context.Context, repo *repo messageID := generateMessageIDForActionsWorkflowRunStatusEmail(repo, run) metadataHeaders := generateMetadataHeaders(repo) - jobs, err := actions_model.GetRunJobsByRunID(ctx, run.ID) - if err != nil { - log.Error("GetRunJobsByRunID: %v", err) - return - } sort.SliceStable(jobs, func(i, j int) bool { si, sj := jobs[i].Status, jobs[j].Status /* @@ -111,11 +117,11 @@ func composeAndSendActionsWorkflowRunStatusEmail(ctx context.Context, repo *repo "Jobs": convertedJobs, "locale": locale, }); err != nil { - log.Error("ExecuteTemplate [%s]: %v", tplWorkflowRun, err) - return + return err } msgs := make([]*sender_service.Message, 0, len(tos)) for _, rec := range tos { + log.Trace("Sending actions email to %s (UID: %d)", rec.Name, rec.ID) msg := sender_service.NewMessageFrom( rec.Email, displayName, @@ -135,14 +141,16 @@ func composeAndSendActionsWorkflowRunStatusEmail(ctx context.Context, repo *repo } SendAsync(msgs...) } + + return nil } -func MailActionsTrigger(ctx context.Context, sender *user_model.User, repo *repo_model.Repository, run *actions_model.ActionRun) { +func MailActionsTrigger(ctx context.Context, sender *user_model.User, repo *repo_model.Repository, run *actions_model.ActionRun) error { if setting.MailService == nil { - return + return nil } - if run.Status.IsSkipped() { - return + if !run.Status.IsDone() || run.Status.IsSkipped() { + return nil } recipients := make([]*user_model.User, 0) @@ -151,8 +159,7 @@ func MailActionsTrigger(ctx context.Context, sender *user_model.User, repo *repo notifyPref, err := user_model.GetUserSetting(ctx, sender.ID, user_model.SettingsKeyEmailNotificationGiteaActions, user_model.SettingEmailNotificationGiteaActionsFailureOnly) if err != nil { - log.Error("GetUserSetting: %v", err) - return + return err } if notifyPref == user_model.SettingEmailNotificationGiteaActionsAll || !run.Status.IsSuccess() && notifyPref != user_model.SettingEmailNotificationGiteaActionsDisabled { recipients = append(recipients, sender) @@ -160,6 +167,8 @@ func MailActionsTrigger(ctx context.Context, sender *user_model.User, repo *repo } if len(recipients) > 0 { - composeAndSendActionsWorkflowRunStatusEmail(ctx, repo, run, sender, recipients) + log.Debug("MailActionsTrigger: Initiate email composition") + return composeAndSendActionsWorkflowRunStatusEmail(ctx, repo, run, sender, recipients) } + return nil } diff --git a/services/mailer/notify.go b/services/mailer/notify.go index c008685e131..5921021ce82 100644 --- a/services/mailer/notify.go +++ b/services/mailer/notify.go @@ -128,7 +128,7 @@ func (m *mailNotifier) IssueChangeAssignee(ctx context.Context, doer *user_model func (m *mailNotifier) PullRequestReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { if isRequest && doer.ID != reviewer.ID && reviewer.EmailNotificationsPreference != user_model.EmailNotificationsDisabled { - ct := fmt.Sprintf("Requested to review %s.", issue.HTMLURL()) + ct := fmt.Sprintf("Requested to review %s.", issue.HTMLURL(ctx)) if err := SendIssueAssignedMail(ctx, issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil { log.Error("Error in SendIssueAssignedMail for issue[%d] to reviewer[%d]: %v", issue.ID, reviewer.ID, err) } @@ -208,8 +208,7 @@ func (m *mailNotifier) RepoPendingTransfer(ctx context.Context, doer, newOwner * } func (m *mailNotifier) WorkflowRunStatusUpdate(ctx context.Context, repo *repo_model.Repository, sender *user_model.User, run *actions_model.ActionRun) { - if !run.Status.IsDone() { - return + if err := MailActionsTrigger(ctx, sender, repo, run); err != nil { + log.Error("MailActionsTrigger: %v", err) } - MailActionsTrigger(ctx, sender, repo, run) } diff --git a/services/markup/renderhelper_mention_test.go b/services/markup/renderhelper_mention_test.go index d54ab13a484..11aa7b2132e 100644 --- a/services/markup/renderhelper_mention_test.go +++ b/services/markup/renderhelper_mention_test.go @@ -8,7 +8,6 @@ import ( "net/http/httptest" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/user" gitea_context "code.gitea.io/gitea/services/context" @@ -45,7 +44,7 @@ func TestRenderHelperMention(t *testing.T) { assert.True(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPublic)) assert.False(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPrivate)) - giteaCtx.Doer, err = user.GetUserByName(db.DefaultContext, userPrivate) + giteaCtx.Doer, err = user.GetUserByName(t.Context(), userPrivate) assert.NoError(t, err) assert.True(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPublic)) assert.True(t, FormalRenderHelperFuncs().IsUsernameMentionable(giteaCtx, userPrivate)) diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go index 1970c0550c4..5e6fe6cc054 100644 --- a/services/migrations/gitea_uploader_test.go +++ b/services/migrations/gitea_uploader_test.go @@ -45,7 +45,7 @@ func TestGiteaUploadRepo(t *testing.T) { uploader = NewGiteaLocalUploader(graceful.GetManager().HammerContext(), user, user.Name, repoName) ) - err := migrateRepository(db.DefaultContext, user, downloader, uploader, base.MigrateOptions{ + err := migrateRepository(t.Context(), user, downloader, uploader, base.MigrateOptions{ CloneAddr: "https://github.com/go-xorm/builder", RepoName: repoName, AuthUsername: "", @@ -66,14 +66,14 @@ func TestGiteaUploadRepo(t *testing.T) { assert.True(t, repo.HasWiki()) assert.Equal(t, repo_model.RepositoryReady, repo.Status) - milestones, err := db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + milestones, err := db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: repo.ID, IsClosed: optional.Some(false), }) assert.NoError(t, err) assert.Len(t, milestones, 1) - milestones, err = db.Find[issues_model.Milestone](db.DefaultContext, issues_model.FindMilestoneOptions{ + milestones, err = db.Find[issues_model.Milestone](t.Context(), issues_model.FindMilestoneOptions{ RepoID: repo.ID, IsClosed: optional.Some(true), }) @@ -84,7 +84,7 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, labels, 12) - releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ + releases, err := db.Find[repo_model.Release](t.Context(), repo_model.FindReleasesOptions{ ListOptions: db.ListOptions{ PageSize: 10, Page: 0, @@ -95,7 +95,7 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, releases, 8) - releases, err = db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ + releases, err = db.Find[repo_model.Release](t.Context(), repo_model.FindReleasesOptions{ ListOptions: db.ListOptions{ PageSize: 10, Page: 0, @@ -106,23 +106,23 @@ func TestGiteaUploadRepo(t *testing.T) { assert.NoError(t, err) assert.Len(t, releases, 1) - issues, err := issues_model.Issues(db.DefaultContext, &issues_model.IssuesOptions{ + issues, err := issues_model.Issues(t.Context(), &issues_model.IssuesOptions{ RepoIDs: []int64{repo.ID}, IsPull: optional.Some(false), SortType: "oldest", }) assert.NoError(t, err) assert.Len(t, issues, 15) - assert.NoError(t, issues[0].LoadDiscussComments(db.DefaultContext)) + assert.NoError(t, issues[0].LoadDiscussComments(t.Context())) assert.Empty(t, issues[0].Comments) - pulls, _, err := issues_model.PullRequests(db.DefaultContext, repo.ID, &issues_model.PullRequestsOptions{ + pulls, _, err := issues_model.PullRequests(t.Context(), repo.ID, &issues_model.PullRequestsOptions{ SortType: "oldest", }) assert.NoError(t, err) assert.Len(t, pulls, 30) - assert.NoError(t, pulls[0].LoadIssue(db.DefaultContext)) - assert.NoError(t, pulls[0].Issue.LoadDiscussComments(db.DefaultContext)) + assert.NoError(t, pulls[0].LoadIssue(t.Context())) + assert.NoError(t, pulls[0].Issue.LoadDiscussComments(t.Context())) assert.Len(t, pulls[0].Issue.Comments, 2) } @@ -214,7 +214,7 @@ func TestGiteaUploadRemapExternalUser(t *testing.T) { LoginSourceID: 0, Provider: structs.GiteaService.Name(), } - err = user_model.LinkExternalToUser(db.DefaultContext, linkedUser, externalLoginUser) + err = user_model.LinkExternalToUser(t.Context(), linkedUser, externalLoginUser) assert.NoError(t, err) // @@ -236,22 +236,22 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { // fromRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) baseRef := "master" - assert.NoError(t, git.InitRepository(git.DefaultContext, fromRepo.RepoPath(), false, fromRepo.ObjectFormatName)) - err := git.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(git.DefaultContext, &git.RunOpts{Dir: fromRepo.RepoPath()}) + assert.NoError(t, git.InitRepository(t.Context(), fromRepo.RepoPath(), false, fromRepo.ObjectFormatName)) + err := git.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(t.Context(), &git.RunOpts{Dir: fromRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte("# Testing Repository\n\nOriginally created in: "+fromRepo.RepoPath()), 0o644)) - assert.NoError(t, git.AddChanges(fromRepo.RepoPath(), true)) + assert.NoError(t, git.AddChanges(t.Context(), fromRepo.RepoPath(), true)) signature := git.Signature{ Email: "test@example.com", Name: "test", When: time.Now(), } - assert.NoError(t, git.CommitChanges(fromRepo.RepoPath(), git.CommitChangesOptions{ + assert.NoError(t, git.CommitChanges(t.Context(), fromRepo.RepoPath(), git.CommitChangesOptions{ Committer: &signature, Author: &signature, Message: "Initial Commit", })) - fromGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, fromRepo) + fromGitRepo, err := gitrepo.OpenRepository(t.Context(), fromRepo) assert.NoError(t, err) defer fromGitRepo.Close() baseSHA, err := fromGitRepo.GetBranchCommitID(baseRef) @@ -261,12 +261,12 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { // fromRepo branch1 // headRef := "branch1" - _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(headRef).RunStdString(git.DefaultContext, &git.RunOpts{Dir: fromRepo.RepoPath()}) + _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(headRef).RunStdString(t.Context(), &git.RunOpts{Dir: fromRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte("SOMETHING"), 0o644)) - assert.NoError(t, git.AddChanges(fromRepo.RepoPath(), true)) + assert.NoError(t, git.AddChanges(t.Context(), fromRepo.RepoPath(), true)) signature.When = time.Now() - assert.NoError(t, git.CommitChanges(fromRepo.RepoPath(), git.CommitChangesOptions{ + assert.NoError(t, git.CommitChanges(t.Context(), fromRepo.RepoPath(), git.CommitChangesOptions{ Committer: &signature, Author: &signature, Message: "Pull request", @@ -282,19 +282,19 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { // forkHeadRef := "branch2" forkRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 8}) - assert.NoError(t, git.CloneWithArgs(git.DefaultContext, nil, fromRepo.RepoPath(), forkRepo.RepoPath(), git.CloneRepoOptions{ + assert.NoError(t, git.Clone(t.Context(), fromRepo.RepoPath(), forkRepo.RepoPath(), git.CloneRepoOptions{ Branch: headRef, })) - _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(forkHeadRef).RunStdString(git.DefaultContext, &git.RunOpts{Dir: forkRepo.RepoPath()}) + _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(forkHeadRef).RunStdString(t.Context(), &git.RunOpts{Dir: forkRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(forkRepo.RepoPath(), "README.md"), []byte("# branch2 "+forkRepo.RepoPath()), 0o644)) - assert.NoError(t, git.AddChanges(forkRepo.RepoPath(), true)) - assert.NoError(t, git.CommitChanges(forkRepo.RepoPath(), git.CommitChangesOptions{ + assert.NoError(t, git.AddChanges(t.Context(), forkRepo.RepoPath(), true)) + assert.NoError(t, git.CommitChanges(t.Context(), forkRepo.RepoPath(), git.CommitChangesOptions{ Committer: &signature, Author: &signature, Message: "branch2 commit", })) - forkGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, forkRepo) + forkGitRepo, err := gitrepo.OpenRepository(t.Context(), forkRepo) assert.NoError(t, err) defer forkGitRepo.Close() forkHeadSHA, err := forkGitRepo.GetBranchCommitID(forkHeadRef) diff --git a/services/migrations/github.go b/services/migrations/github.go index c6cd6ea1733..a8a89dce0bc 100644 --- a/services/migrations/github.go +++ b/services/migrations/github.go @@ -354,7 +354,8 @@ func (g *GithubDownloaderV3) convertGithubRelease(ctx context.Context, rel *gith // Prevent open redirect if !hasBaseURL(redirectURL, g.baseURL) && - !hasBaseURL(redirectURL, "https://objects.githubusercontent.com/") { + !hasBaseURL(redirectURL, "https://objects.githubusercontent.com/") && + !hasBaseURL(redirectURL, "https://release-assets.githubusercontent.com/") { WarnAndNotice("Unexpected AssetURL for assetID[%d] in %s: %s", asset.GetID(), g, redirectURL) return io.NopCloser(strings.NewReader(redirectURL)), nil diff --git a/services/migrations/onedev.go b/services/migrations/onedev.go index e052cba0cca..9917bdae3c1 100644 --- a/services/migrations/onedev.go +++ b/services/migrations/onedev.go @@ -6,6 +6,7 @@ package migrations import ( "context" "fmt" + "io" "net/http" "net/url" "strconv" @@ -16,8 +17,12 @@ import ( "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/structs" + + "github.com/hashicorp/go-version" ) +const OneDevRequiredVersion = "12.0.1" + var ( _ base.Downloader = &OneDevDownloader{} _ base.DownloaderFactory = &OneDevDownloaderFactory{} @@ -37,23 +42,14 @@ func (f *OneDevDownloaderFactory) New(ctx context.Context, opts base.MigrateOpti return nil, err } - var repoName string - - fields := strings.Split(strings.Trim(u.Path, "/"), "/") - if len(fields) == 2 && fields[0] == "projects" { - repoName = fields[1] - } else if len(fields) == 1 { - repoName = fields[0] - } else { - return nil, fmt.Errorf("invalid path: %s", u.Path) - } + repoPath := strings.Trim(u.Path, "/") u.Path = "" u.Fragment = "" - log.Trace("Create onedev downloader. BaseURL: %v RepoName: %s", u, repoName) + log.Trace("Create onedev downloader. BaseURL: %v RepoPath: %s", u, repoPath) - return NewOneDevDownloader(ctx, u, opts.AuthUsername, opts.AuthPassword, repoName), nil + return NewOneDevDownloader(ctx, u, opts.AuthUsername, opts.AuthPassword, repoPath), nil } // GitServiceType returns the type of git service @@ -62,9 +58,9 @@ func (f *OneDevDownloaderFactory) GitServiceType() structs.GitServiceType { } type onedevUser struct { - ID int64 `json:"id"` - Name string `json:"name"` - Email string `json:"email"` + ID int64 + Name string + Email string } // OneDevDownloader implements a Downloader interface to get repository information @@ -73,7 +69,7 @@ type OneDevDownloader struct { base.NullDownloader client *http.Client baseURL *url.URL - repoName string + repoPath string repoID int64 maxIssueIndex int64 userMap map[int64]*onedevUser @@ -81,10 +77,10 @@ type OneDevDownloader struct { } // NewOneDevDownloader creates a new downloader -func NewOneDevDownloader(_ context.Context, baseURL *url.URL, username, password, repoName string) *OneDevDownloader { +func NewOneDevDownloader(_ context.Context, baseURL *url.URL, username, password, repoPath string) *OneDevDownloader { downloader := &OneDevDownloader{ baseURL: baseURL, - repoName: repoName, + repoPath: repoPath, client: &http.Client{ Transport: &http.Transport{ Proxy: func(req *http.Request) (*url.URL, error) { @@ -104,14 +100,14 @@ func NewOneDevDownloader(_ context.Context, baseURL *url.URL, username, password // String implements Stringer func (d *OneDevDownloader) String() string { - return fmt.Sprintf("migration from oneDev server %s [%d]/%s", d.baseURL, d.repoID, d.repoName) + return fmt.Sprintf("migration from oneDev server %s [%d]/%s", d.baseURL, d.repoID, d.repoPath) } func (d *OneDevDownloader) LogString() string { if d == nil { return "" } - return fmt.Sprintf("", d.baseURL, d.repoID, d.repoName) + return fmt.Sprintf("", d.baseURL, d.repoID, d.repoPath) } func (d *OneDevDownloader) callAPI(ctx context.Context, endpoint string, parameter map[string]string, result any) error { @@ -139,23 +135,54 @@ func (d *OneDevDownloader) callAPI(ctx context.Context, endpoint string, paramet } defer resp.Body.Close() + // special case to read OneDev server version, which is not valid JSON + if presult, ok := result.(**version.Version); ok { + bytes, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + vers, err := version.NewVersion(string(bytes)) + if err != nil { + return err + } + *presult = vers + return nil + } + decoder := json.NewDecoder(resp.Body) return decoder.Decode(&result) } // GetRepoInfo returns repository information func (d *OneDevDownloader) GetRepoInfo(ctx context.Context) (*base.Repository, error) { + // check OneDev server version + var serverVersion *version.Version + err := d.callAPI( + ctx, + "/~api/version/server", + nil, + &serverVersion, + ) + if err != nil { + return nil, fmt.Errorf("failed to get OneDev server version; OneDev %s or newer required", OneDevRequiredVersion) + } + requiredVersion, _ := version.NewVersion(OneDevRequiredVersion) + if serverVersion.LessThan(requiredVersion) { + return nil, fmt.Errorf("OneDev %s or newer required; currently running OneDev %s", OneDevRequiredVersion, serverVersion) + } + info := make([]struct { ID int64 `json:"id"` Name string `json:"name"` + Path string `json:"path"` Description string `json:"description"` }, 0, 1) - err := d.callAPI( + err = d.callAPI( ctx, - "/api/projects", + "/~api/projects", map[string]string{ - "query": `"Name" is "` + d.repoName + `"`, + "query": `"Path" is "` + d.repoPath + `"`, "offset": "0", "count": "1", }, @@ -165,16 +192,12 @@ func (d *OneDevDownloader) GetRepoInfo(ctx context.Context) (*base.Repository, e return nil, err } if len(info) != 1 { - return nil, fmt.Errorf("Project %s not found", d.repoName) + return nil, fmt.Errorf("Project %s not found", d.repoPath) } d.repoID = info[0].ID - cloneURL, err := d.baseURL.Parse(info[0].Name) - if err != nil { - return nil, err - } - originalURL, err := d.baseURL.Parse("/projects/" + info[0].Name) + cloneURL, err := d.baseURL.Parse(info[0].Path) if err != nil { return nil, err } @@ -183,25 +206,25 @@ func (d *OneDevDownloader) GetRepoInfo(ctx context.Context) (*base.Repository, e Name: info[0].Name, Description: info[0].Description, CloneURL: cloneURL.String(), - OriginalURL: originalURL.String(), + OriginalURL: cloneURL.String(), }, nil } // GetMilestones returns milestones func (d *OneDevDownloader) GetMilestones(ctx context.Context) ([]*base.Milestone, error) { - rawMilestones := make([]struct { - ID int64 `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - DueDate *time.Time `json:"dueDate"` - Closed bool `json:"closed"` - }, 0, 100) - - endpoint := fmt.Sprintf("/api/projects/%d/milestones", d.repoID) + endpoint := fmt.Sprintf("/~api/projects/%d/iterations", d.repoID) milestones := make([]*base.Milestone, 0, 100) offset := 0 for { + rawMilestones := make([]struct { + ID int64 `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + DueDay int64 `json:"dueDay"` + Closed bool `json:"closed"` + }, 0, 100) + err := d.callAPI( ctx, endpoint, @@ -221,16 +244,26 @@ func (d *OneDevDownloader) GetMilestones(ctx context.Context) ([]*base.Milestone for _, milestone := range rawMilestones { d.milestoneMap[milestone.ID] = milestone.Name - closed := milestone.DueDate - if !milestone.Closed { - closed = nil + + var dueDate *time.Time + if milestone.DueDay != 0 { + d := time.Unix(milestone.DueDay*24*60*60, 0) + dueDate = &d + } + + var closedDate *time.Time + state := "open" + if milestone.Closed { + closedDate = dueDate + state = "closed" } milestones = append(milestones, &base.Milestone{ Title: milestone.Name, Description: milestone.Description, - Deadline: milestone.DueDate, - Closed: closed, + Deadline: dueDate, + Closed: closedDate, + State: state, }) } } @@ -273,6 +306,10 @@ type onedevIssueContext struct { // GetIssues returns issues func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([]*base.Issue, bool, error) { + type Field struct { + Name string `json:"name"` + Value string `json:"value"` + } rawIssues := make([]struct { ID int64 `json:"id"` Number int64 `json:"number"` @@ -281,15 +318,17 @@ func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([] Description string `json:"description"` SubmitterID int64 `json:"submitterId"` SubmitDate time.Time `json:"submitDate"` + Fields []Field `json:"fields"` }, 0, perPage) err := d.callAPI( ctx, - "/api/issues", + "/~api/issues", map[string]string{ - "query": `"Project" is "` + d.repoName + `"`, - "offset": strconv.Itoa((page - 1) * perPage), - "count": strconv.Itoa(perPage), + "query": `"Project" is "` + d.repoPath + `"`, + "offset": strconv.Itoa((page - 1) * perPage), + "count": strconv.Itoa(perPage), + "withFields": "true", }, &rawIssues, ) @@ -299,22 +338,8 @@ func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([] issues := make([]*base.Issue, 0, len(rawIssues)) for _, issue := range rawIssues { - fields := make([]struct { - Name string `json:"name"` - Value string `json:"value"` - }, 0, 10) - err := d.callAPI( - ctx, - fmt.Sprintf("/api/issues/%d/fields", issue.ID), - nil, - &fields, - ) - if err != nil { - return nil, false, err - } - var label *base.Label - for _, field := range fields { + for _, field := range issue.Fields { if field.Name == "Type" { label = &base.Label{Name: field.Value} break @@ -327,7 +352,7 @@ func (d *OneDevDownloader) GetIssues(ctx context.Context, page, perPage int) ([] }, 0, 10) err = d.callAPI( ctx, - fmt.Sprintf("/api/issues/%d/milestones", issue.ID), + fmt.Sprintf("/~api/issues/%d/iterations", issue.ID), nil, &milestones, ) @@ -383,9 +408,9 @@ func (d *OneDevDownloader) GetComments(ctx context.Context, commentable base.Com var endpoint string if context.IsPullRequest { - endpoint = fmt.Sprintf("/api/pull-requests/%d/comments", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/pulls/%d/comments", commentable.GetForeignIndex()) } else { - endpoint = fmt.Sprintf("/api/issues/%d/comments", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/issues/%d/comments", commentable.GetForeignIndex()) } err := d.callAPI( @@ -405,9 +430,9 @@ func (d *OneDevDownloader) GetComments(ctx context.Context, commentable base.Com }, 0, 100) if context.IsPullRequest { - endpoint = fmt.Sprintf("/api/pull-requests/%d/changes", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/pulls/%d/changes", commentable.GetForeignIndex()) } else { - endpoint = fmt.Sprintf("/api/issues/%d/changes", commentable.GetForeignIndex()) + endpoint = fmt.Sprintf("/~api/issues/%d/changes", commentable.GetForeignIndex()) } err = d.callAPI( @@ -468,26 +493,24 @@ func (d *OneDevDownloader) GetComments(ctx context.Context, commentable base.Com // GetPullRequests returns pull requests func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage int) ([]*base.PullRequest, bool, error) { rawPullRequests := make([]struct { - ID int64 `json:"id"` - Number int64 `json:"number"` - Title string `json:"title"` - SubmitterID int64 `json:"submitterId"` - SubmitDate time.Time `json:"submitDate"` - Description string `json:"description"` - TargetBranch string `json:"targetBranch"` - SourceBranch string `json:"sourceBranch"` - BaseCommitHash string `json:"baseCommitHash"` - CloseInfo *struct { - Date *time.Time `json:"date"` - Status string `json:"status"` - } + ID int64 `json:"id"` + Number int64 `json:"number"` + Title string `json:"title"` + SubmitterID int64 `json:"submitterId"` + SubmitDate time.Time `json:"submitDate"` + Description string `json:"description"` + TargetBranch string `json:"targetBranch"` + SourceBranch string `json:"sourceBranch"` + BaseCommitHash string `json:"baseCommitHash"` + CloseDate *time.Time `json:"closeDate"` + Status string `json:"status"` // Possible values: OPEN, MERGED, DISCARDED }, 0, perPage) err := d.callAPI( ctx, - "/api/pull-requests", + "/~api/pulls", map[string]string{ - "query": `"Target Project" is "` + d.repoName + `"`, + "query": `"Target Project" is "` + d.repoPath + `"`, "offset": strconv.Itoa((page - 1) * perPage), "count": strconv.Itoa(perPage), }, @@ -507,7 +530,7 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in } err := d.callAPI( ctx, - fmt.Sprintf("/api/pull-requests/%d/merge-preview", pr.ID), + fmt.Sprintf("/~api/pulls/%d/merge-preview", pr.ID), nil, &mergePreview, ) @@ -519,12 +542,12 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in merged := false var closeTime *time.Time var mergedTime *time.Time - if pr.CloseInfo != nil { + if pr.Status != "OPEN" { state = "closed" - closeTime = pr.CloseInfo.Date - if pr.CloseInfo.Status == "MERGED" { // "DISCARDED" + closeTime = pr.CloseDate + if pr.Status == "MERGED" { // "DISCARDED" merged = true - mergedTime = pr.CloseInfo.Date + mergedTime = pr.CloseDate } } poster := d.tryGetUser(ctx, pr.SubmitterID) @@ -545,12 +568,12 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in Head: base.PullRequestBranch{ Ref: pr.SourceBranch, SHA: mergePreview.HeadCommitHash, - RepoName: d.repoName, + RepoName: d.repoPath, }, Base: base.PullRequestBranch{ Ref: pr.TargetBranch, SHA: mergePreview.TargetHeadCommitHash, - RepoName: d.repoName, + RepoName: d.repoPath, }, ForeignIndex: pr.ID, Context: onedevIssueContext{IsPullRequest: true}, @@ -566,18 +589,14 @@ func (d *OneDevDownloader) GetPullRequests(ctx context.Context, page, perPage in // GetReviews returns pull requests reviews func (d *OneDevDownloader) GetReviews(ctx context.Context, reviewable base.Reviewable) ([]*base.Review, error) { rawReviews := make([]struct { - ID int64 `json:"id"` - UserID int64 `json:"userId"` - Result *struct { - Commit string `json:"commit"` - Approved bool `json:"approved"` - Comment string `json:"comment"` - } + ID int64 `json:"id"` + UserID int64 `json:"userId"` + Status string `json:"status"` // Possible values: PENDING, APPROVED, REQUESTED_FOR_CHANGES, EXCLUDED }, 0, 100) err := d.callAPI( ctx, - fmt.Sprintf("/api/pull-requests/%d/reviews", reviewable.GetForeignIndex()), + fmt.Sprintf("/~api/pulls/%d/reviews", reviewable.GetForeignIndex()), nil, &rawReviews, ) @@ -589,14 +608,11 @@ func (d *OneDevDownloader) GetReviews(ctx context.Context, reviewable base.Revie for _, review := range rawReviews { state := base.ReviewStatePending content := "" - if review.Result != nil { - if len(review.Result.Comment) > 0 { - state = base.ReviewStateCommented - content = review.Result.Comment - } - if review.Result.Approved { - state = base.ReviewStateApproved - } + switch review.Status { + case "APPROVED": + state = base.ReviewStateApproved + case "REQUESTED_FOR_CHANGES": + state = base.ReviewStateChangesRequested } poster := d.tryGetUser(ctx, review.UserID) @@ -620,17 +636,52 @@ func (d *OneDevDownloader) GetTopics(_ context.Context) ([]string, error) { func (d *OneDevDownloader) tryGetUser(ctx context.Context, userID int64) *onedevUser { user, ok := d.userMap[userID] if !ok { + // get user name + type RawUser struct { + Name string `json:"name"` + } + var rawUser RawUser err := d.callAPI( ctx, - fmt.Sprintf("/api/users/%d", userID), + fmt.Sprintf("/~api/users/%d", userID), nil, - &user, + &rawUser, ) - if err != nil { - user = &onedevUser{ - Name: fmt.Sprintf("User %d", userID), + var userName string + if err == nil { + userName = rawUser.Name + } else { + userName = fmt.Sprintf("User %d", userID) + } + + // get (primary) user Email address + rawEmailAddresses := make([]struct { + Value string `json:"value"` + Primary bool `json:"primary"` + }, 0, 10) + err = d.callAPI( + ctx, + fmt.Sprintf("/~api/users/%d/email-addresses", userID), + nil, + &rawEmailAddresses, + ) + var userEmail string + if err == nil { + for _, email := range rawEmailAddresses { + if userEmail == "" || email.Primary { + userEmail = email.Value + } + if email.Primary { + break + } } } + + user = &onedevUser{ + ID: userID, + Name: userName, + Email: userEmail, + } d.userMap[userID] = user } diff --git a/services/oauth2_provider/access_token.go b/services/oauth2_provider/access_token.go index 5a190d86165..dce4ac765b7 100644 --- a/services/oauth2_provider/access_token.go +++ b/services/oauth2_provider/access_token.go @@ -196,7 +196,7 @@ func NewAccessTokenResponse(ctx context.Context, grant *auth.OAuth2Grant, server if grant.ScopeContains("profile") { idToken.Name = user.DisplayName() idToken.PreferredUsername = user.Name - idToken.Profile = user.HTMLURL() + idToken.Profile = user.HTMLURL(ctx) idToken.Picture = user.AvatarLink(ctx) idToken.Website = user.Website idToken.Locale = user.Language diff --git a/services/org/org.go b/services/org/org.go index 3d30ae21a39..142a643f9fc 100644 --- a/services/org/org.go +++ b/services/org/org.go @@ -8,13 +8,17 @@ import ( "fmt" actions_model "code.gitea.io/gitea/models/actions" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" org_model "code.gitea.io/gitea/models/organization" packages_model "code.gitea.io/gitea/models/packages" + access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" secret_model "code.gitea.io/gitea/models/secret" user_model "code.gitea.io/gitea/models/user" + issue_indexer "code.gitea.io/gitea/modules/indexer/issues" "code.gitea.io/gitea/modules/storage" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" repo_service "code.gitea.io/gitea/services/repository" ) @@ -102,3 +106,70 @@ func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge return nil } + +func updateOrgRepoForVisibilityChanged(ctx context.Context, repo *repo_model.Repository, makePrivate bool) error { + // Organization repository need to recalculate access table when visibility is changed. + if err := access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { + return fmt.Errorf("recalculateTeamAccesses: %w", err) + } + + if makePrivate { + if _, err := db.GetEngine(ctx).Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{ + IsPrivate: true, + }); err != nil { + return err + } + + if err := repo_model.ClearRepoStars(ctx, repo.ID); err != nil { + return err + } + } + + // Create/Remove git-daemon-export-ok for git-daemon... + if err := repo_service.CheckDaemonExportOK(ctx, repo); err != nil { + return err + } + + // If visibility is changed, we need to update the issue indexer. + // Since the data in the issue indexer have field to indicate if the repo is public or not. + // FIXME: it should check organization visibility instead of repository visibility only. + issue_indexer.UpdateRepoIndexer(ctx, repo.ID) + + forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID) + if err != nil { + return fmt.Errorf("getRepositoriesByForkID: %w", err) + } + for i := range forkRepos { + if err := updateOrgRepoForVisibilityChanged(ctx, forkRepos[i], makePrivate); err != nil { + return fmt.Errorf("updateRepoForVisibilityChanged[%s]: %w", forkRepos[i].FullName(), err) + } + } + return nil +} + +func ChangeOrganizationVisibility(ctx context.Context, org *org_model.Organization, visibility structs.VisibleType) error { + if org.Visibility == visibility { + return nil + } + + org.Visibility = visibility + // FIXME: If it's a big forks network(forks and sub forks), the database transaction will be too long to fail. + return db.WithTx(ctx, func(ctx context.Context) error { + if err := user_model.UpdateUserColsNoAutoTime(ctx, org.AsUser(), "visibility"); err != nil { + return err + } + + repos, _, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{ + Actor: org.AsUser(), Private: true, ListOptions: db.ListOptionsAll, + }) + if err != nil { + return err + } + for _, repo := range repos { + if err := updateOrgRepoForVisibilityChanged(ctx, repo, visibility == structs.VisibleTypePrivate); err != nil { + return fmt.Errorf("updateOrgRepoForVisibilityChanged: %w", err) + } + } + return nil + }) +} diff --git a/services/org/org_test.go b/services/org/org_test.go index 791404c5c89..5fdc1a6fd5e 100644 --- a/services/org/org_test.go +++ b/services/org/org_test.go @@ -6,7 +6,6 @@ package org import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -22,17 +21,17 @@ func TestMain(m *testing.M) { func TestDeleteOrganization(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 6}) - assert.NoError(t, DeleteOrganization(db.DefaultContext, org, false)) + assert.NoError(t, DeleteOrganization(t.Context(), org, false)) unittest.AssertNotExistsBean(t, &organization.Organization{ID: 6}) unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: 6}) unittest.AssertNotExistsBean(t, &organization.Team{OrgID: 6}) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - err := DeleteOrganization(db.DefaultContext, org, false) + err := DeleteOrganization(t.Context(), org, false) assert.Error(t, err) assert.True(t, repo_model.IsErrUserOwnRepos(err)) user := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 5}) - assert.Error(t, DeleteOrganization(db.DefaultContext, user, false)) + assert.Error(t, DeleteOrganization(t.Context(), user, false)) unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) } diff --git a/services/org/team.go b/services/org/team.go index 773bd11f49b..633056cf95f 100644 --- a/services/org/team.go +++ b/services/org/team.go @@ -15,6 +15,7 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" @@ -259,10 +260,9 @@ func AddTeamMember(ctx context.Context, team *organization.Team, user *user_mode log.Error("GetTeamRepositories failed: %v", err) } - // FIXME: in the goroutine, it can't access the "ctx", it could only use db.DefaultContext at the moment go func(repos []*repo_model.Repository) { for _, repo := range repos { - if err = repo_model.WatchRepo(db.DefaultContext, user, repo, true); err != nil { + if err = repo_model.WatchRepo(graceful.GetManager().ShutdownContext(), user, repo, true); err != nil { log.Error("watch repo failed: %v", err) } } diff --git a/services/org/team_test.go b/services/org/team_test.go index c1a69d8ee73..a5e01e7a54f 100644 --- a/services/org/team_test.go +++ b/services/org/team_test.go @@ -8,7 +8,6 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" @@ -25,7 +24,7 @@ func TestTeam_AddMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, AddTeamMember(db.DefaultContext, team, user)) + assert.NoError(t, AddTeamMember(t.Context(), team, user)) unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}, &user_model.User{ID: team.OrgID}) } @@ -44,7 +43,7 @@ func TestTeam_RemoveMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, RemoveTeamMember(db.DefaultContext, team, user)) + assert.NoError(t, RemoveTeamMember(t.Context(), team, user)) unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) } @@ -59,7 +58,7 @@ func TestTeam_RemoveMember(t *testing.T) { testSuccess(team2, user2) testSuccess(team3, user2) - err := RemoveTeamMember(db.DefaultContext, team1, user2) + err := RemoveTeamMember(t.Context(), team1, user2) assert.True(t, organization.IsErrLastOrgOwner(err)) } @@ -68,7 +67,7 @@ func TestNewTeam(t *testing.T) { const teamName = "newTeamName" team := &organization.Team{Name: teamName, OrgID: 3} - assert.NoError(t, NewTeam(db.DefaultContext, team)) + assert.NoError(t, NewTeam(t.Context(), team)) unittest.AssertExistsAndLoadBean(t, &organization.Team{Name: teamName}) unittest.CheckConsistencyFor(t, &organization.Team{}, &user_model.User{ID: team.OrgID}) } @@ -82,7 +81,7 @@ func TestUpdateTeam(t *testing.T) { team.Name = "newName" team.Description = strings.Repeat("A long description!", 100) team.AccessMode = perm.AccessModeAdmin - assert.NoError(t, UpdateTeam(db.DefaultContext, team, true, false)) + assert.NoError(t, UpdateTeam(t.Context(), team, true, false)) team = unittest.AssertExistsAndLoadBean(t, &organization.Team{Name: "newName"}) assert.True(t, strings.HasPrefix(team.Description, "A long description!")) @@ -101,7 +100,7 @@ func TestUpdateTeam2(t *testing.T) { team.LowerName = "owners" team.Name = "Owners" team.Description = strings.Repeat("A long description!", 100) - err := UpdateTeam(db.DefaultContext, team, true, false) + err := UpdateTeam(t.Context(), team, true, false) assert.True(t, organization.IsErrTeamAlreadyExist(err)) unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) @@ -111,7 +110,7 @@ func TestDeleteTeam(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - assert.NoError(t, DeleteTeam(db.DefaultContext, team)) + assert.NoError(t, DeleteTeam(t.Context(), team)) unittest.AssertNotExistsBean(t, &organization.Team{ID: team.ID}) unittest.AssertNotExistsBean(t, &organization.TeamRepo{TeamID: team.ID}) unittest.AssertNotExistsBean(t, &organization.TeamUser{TeamID: team.ID}) @@ -119,7 +118,7 @@ func TestDeleteTeam(t *testing.T) { // check that team members don't have "leftover" access to repos user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - accessMode, err := access_model.AccessLevel(db.DefaultContext, user, repo) + accessMode, err := access_model.AccessLevel(t.Context(), user, repo) assert.NoError(t, err) assert.Less(t, accessMode, perm.AccessModeWrite) } @@ -128,7 +127,7 @@ func TestAddTeamMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, AddTeamMember(db.DefaultContext, team, user)) + assert.NoError(t, AddTeamMember(t.Context(), team, user)) unittest.AssertExistsAndLoadBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}, &user_model.User{ID: team.OrgID}) } @@ -147,7 +146,7 @@ func TestRemoveTeamMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(team *organization.Team, user *user_model.User) { - assert.NoError(t, RemoveTeamMember(db.DefaultContext, team, user)) + assert.NoError(t, RemoveTeamMember(t.Context(), team, user)) unittest.AssertNotExistsBean(t, &organization.TeamUser{UID: user.ID, TeamID: team.ID}) unittest.CheckConsistencyFor(t, &organization.Team{ID: team.ID}) } @@ -162,7 +161,7 @@ func TestRemoveTeamMember(t *testing.T) { testSuccess(team2, user2) testSuccess(team3, user2) - err := RemoveTeamMember(db.DefaultContext, team1, user2) + err := RemoveTeamMember(t.Context(), team1, user2) assert.True(t, organization.IsErrLastOrgOwner(err)) } @@ -171,7 +170,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { testTeamRepositories := func(teamID int64, repoIDs []int64) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) - repos, err := repo_model.GetTeamRepositories(db.DefaultContext, &repo_model.SearchTeamRepoOptions{ + repos, err := repo_model.GetTeamRepositories(t.Context(), &repo_model.SearchTeamRepoOptions{ TeamID: team.ID, }) assert.NoError(t, err, "%s: GetTeamRepositories", team.Name) @@ -179,13 +178,13 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { assert.Len(t, repos, len(repoIDs), "%s: repo count", team.Name) for i, rid := range repoIDs { if rid > 0 { - assert.True(t, repo_service.HasRepository(db.DefaultContext, team, rid), "%s: HasRepository(%d) %d", rid, i) + assert.True(t, repo_service.HasRepository(t.Context(), team, rid), "%s: HasRepository(%d) %d", rid, i) } } } // Get an admin user. - user, err := user_model.GetUserByID(db.DefaultContext, 1) + user, err := user_model.GetUserByID(t.Context(), 1) assert.NoError(t, err, "GetUserByID") // Create org. @@ -195,17 +194,17 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { Type: user_model.UserTypeOrganization, Visibility: structs.VisibleTypePublic, } - assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, user), "CreateOrganization") + assert.NoError(t, organization.CreateOrganization(t.Context(), org, user), "CreateOrganization") // Check Owner team. - ownerTeam, err := org.GetOwnerTeam(db.DefaultContext) + ownerTeam, err := org.GetOwnerTeam(t.Context()) assert.NoError(t, err, "GetOwnerTeam") assert.True(t, ownerTeam.IncludesAllRepositories, "Owner team includes all repositories") // Create repos. repoIDs := make([]int64, 0) for i := range 3 { - r, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user, org.AsUser(), + r, err := repo_service.CreateRepositoryDirectly(t.Context(), user, org.AsUser(), repo_service.CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)}, true) assert.NoError(t, err, "CreateRepository %d", i) if r != nil { @@ -213,7 +212,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { } } // Get fresh copy of Owner team after creating repos. - ownerTeam, err = org.GetOwnerTeam(db.DefaultContext) + ownerTeam, err = org.GetOwnerTeam(t.Context()) assert.NoError(t, err, "GetOwnerTeam") // Create teams and check repositories. @@ -253,7 +252,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { } for i, team := range teams { if i > 0 { // first team is Owner. - assert.NoError(t, NewTeam(db.DefaultContext, team), "%s: NewTeam", team.Name) + assert.NoError(t, NewTeam(t.Context(), team), "%s: NewTeam", team.Name) } testTeamRepositories(team.ID, teamRepos[i]) } @@ -263,12 +262,12 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { teams[4].IncludesAllRepositories = true teamRepos[4] = repoIDs for i, team := range teams { - assert.NoError(t, UpdateTeam(db.DefaultContext, team, false, true), "%s: UpdateTeam", team.Name) + assert.NoError(t, UpdateTeam(t.Context(), team, false, true), "%s: UpdateTeam", team.Name) testTeamRepositories(team.ID, teamRepos[i]) } // Create repo and check teams repositories. - r, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user, org.AsUser(), repo_service.CreateRepoOptions{Name: "repo-last"}, true) + r, err := repo_service.CreateRepositoryDirectly(t.Context(), user, org.AsUser(), repo_service.CreateRepoOptions{Name: "repo-last"}, true) assert.NoError(t, err, "CreateRepository last") if r != nil { repoIDs = append(repoIDs, r.ID) @@ -281,7 +280,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { } // Remove repo and check teams repositories. - assert.NoError(t, repo_service.DeleteRepositoryDirectly(db.DefaultContext, repoIDs[0]), "DeleteRepository") + assert.NoError(t, repo_service.DeleteRepositoryDirectly(t.Context(), repoIDs[0]), "DeleteRepository") teamRepos[0] = repoIDs[1:] teamRepos[1] = repoIDs[1:] teamRepos[3] = repoIDs[1:3] @@ -293,8 +292,8 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { // Wipe created items. for i, rid := range repoIDs { if i > 0 { // first repo already deleted. - assert.NoError(t, repo_service.DeleteRepositoryDirectly(db.DefaultContext, rid), "DeleteRepository %d", i) + assert.NoError(t, repo_service.DeleteRepositoryDirectly(t.Context(), rid), "DeleteRepository %d", i) } } - assert.NoError(t, DeleteOrganization(db.DefaultContext, org, false), "DeleteOrganization") + assert.NoError(t, DeleteOrganization(t.Context(), org, false), "DeleteOrganization") } diff --git a/services/org/user_test.go b/services/org/user_test.go index c61d600d90d..3df9d533560 100644 --- a/services/org/user_test.go +++ b/services/org/user_test.go @@ -6,7 +6,6 @@ package org import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -24,7 +23,7 @@ func TestUser_RemoveMember(t *testing.T) { // remove a user that is a member unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{UID: user4.ID, OrgID: org.ID}) prevNumMembers := org.NumMembers - assert.NoError(t, RemoveOrgUser(db.DefaultContext, org, user4)) + assert.NoError(t, RemoveOrgUser(t.Context(), org, user4)) unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: user4.ID, OrgID: org.ID}) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: org.ID}) @@ -33,7 +32,7 @@ func TestUser_RemoveMember(t *testing.T) { // remove a user that is not a member unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: user5.ID, OrgID: org.ID}) prevNumMembers = org.NumMembers - assert.NoError(t, RemoveOrgUser(db.DefaultContext, org, user5)) + assert.NoError(t, RemoveOrgUser(t.Context(), org, user5)) unittest.AssertNotExistsBean(t, &organization.OrgUser{UID: user5.ID, OrgID: org.ID}) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: org.ID}) @@ -50,7 +49,7 @@ func TestRemoveOrgUser(t *testing.T) { if unittest.GetBean(t, &organization.OrgUser{OrgID: org.ID, UID: user.ID}) != nil { expectedNumMembers-- } - assert.NoError(t, RemoveOrgUser(db.DefaultContext, org, user)) + assert.NoError(t, RemoveOrgUser(t.Context(), org, user)) unittest.AssertNotExistsBean(t, &organization.OrgUser{OrgID: org.ID, UID: user.ID}) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: org.ID}) assert.Equal(t, expectedNumMembers, org.NumMembers) @@ -66,7 +65,7 @@ func TestRemoveOrgUser(t *testing.T) { org3 = unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) testSuccess(org3, user4) - err := RemoveOrgUser(db.DefaultContext, org7, user5) + err := RemoveOrgUser(t.Context(), org7, user5) assert.Error(t, err) assert.True(t, organization.IsErrLastOrgOwner(err)) unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{OrgID: org7.ID, UID: user5.ID}) diff --git a/services/packages/arch/vercmp.go b/services/packages/arch/vercmp.go index d44aa530f03..f4a83d5eb10 100644 --- a/services/packages/arch/vercmp.go +++ b/services/packages/arch/vercmp.go @@ -4,16 +4,13 @@ package arch import ( + "strconv" "strings" "unicode" ) // https://gitlab.archlinux.org/pacman/pacman/-/blob/d55b47e5512808b67bc944feb20c2bcc6c1a4c45/lib/libalpm/version.c -import ( - "strconv" -) - func parseEVR(evr string) (epoch, version, release string) { if before, after, f := strings.Cut(evr, ":"); f { epoch = before diff --git a/services/packages/container/common.go b/services/packages/container/common.go index 02cbff22863..d3e2996a52d 100644 --- a/services/packages/container/common.go +++ b/services/packages/container/common.go @@ -15,7 +15,7 @@ import ( "code.gitea.io/gitea/modules/packages" container_module "code.gitea.io/gitea/modules/packages/container" - "github.com/opencontainers/image-spec/specs-go/v1" + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) // UpdateRepositoryNames updates the repository name property for all packages of the specific owner diff --git a/services/projects/issue_test.go b/services/projects/issue_test.go index e76d31e7574..7255cdfe527 100644 --- a/services/projects/issue_test.go +++ b/services/projects/issue_test.go @@ -31,10 +31,10 @@ func Test_Projects(t *testing.T) { IssueID: 1, ProjectColumnID: 4, } - err := db.Insert(db.DefaultContext, &pi1) + err := db.Insert(t.Context(), &pi1) assert.NoError(t, err) defer func() { - _, err = db.DeleteByID[project_model.ProjectIssue](db.DefaultContext, pi1.ID) + _, err = db.DeleteByID[project_model.ProjectIssue](t.Context(), pi1.ID) assert.NoError(t, err) }() @@ -43,14 +43,14 @@ func Test_Projects(t *testing.T) { IssueID: 4, ProjectColumnID: 4, } - err = db.Insert(db.DefaultContext, &pi2) + err = db.Insert(t.Context(), &pi2) assert.NoError(t, err) defer func() { - _, err = db.DeleteByID[project_model.ProjectIssue](db.DefaultContext, pi2.ID) + _, err = db.DeleteByID[project_model.ProjectIssue](t.Context(), pi2.ID) assert.NoError(t, err) }() - projects, err := db.Find[project_model.Project](db.DefaultContext, project_model.SearchOptions{ + projects, err := db.Find[project_model.Project](t.Context(), project_model.SearchOptions{ OwnerID: user2.ID, }) assert.NoError(t, err) @@ -58,7 +58,7 @@ func Test_Projects(t *testing.T) { assert.EqualValues(t, 4, projects[0].ID) t.Run("Authenticated user", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ Owner: user2, Doer: user2, }) @@ -68,7 +68,7 @@ func Test_Projects(t *testing.T) { }) t.Run("Anonymous user", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ AllPublic: true, }) assert.NoError(t, err) @@ -77,7 +77,7 @@ func Test_Projects(t *testing.T) { }) t.Run("Authenticated user with no permission to the private repo", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ Owner: user2, Doer: user4, }) @@ -94,10 +94,10 @@ func Test_Projects(t *testing.T) { Type: project_model.TypeOrganization, TemplateType: project_model.TemplateTypeBasicKanban, } - err := project_model.NewProject(db.DefaultContext, &project1) + err := project_model.NewProject(t.Context(), &project1) assert.NoError(t, err) defer func() { - err := project_model.DeleteProjectByID(db.DefaultContext, project1.ID) + err := project_model.DeleteProjectByID(t.Context(), project1.ID) assert.NoError(t, err) }() @@ -105,27 +105,27 @@ func Test_Projects(t *testing.T) { Title: "column 1", ProjectID: project1.ID, } - err = project_model.NewColumn(db.DefaultContext, &column1) + err = project_model.NewColumn(t.Context(), &column1) assert.NoError(t, err) column2 := project_model.Column{ Title: "column 2", ProjectID: project1.ID, } - err = project_model.NewColumn(db.DefaultContext, &column2) + err = project_model.NewColumn(t.Context(), &column2) assert.NoError(t, err) // issue 6 belongs to private repo 3 under org 3 issue6 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 6}) - err = issues_model.IssueAssignOrRemoveProject(db.DefaultContext, issue6, user2, project1.ID, column1.ID) + err = issues_model.IssueAssignOrRemoveProject(t.Context(), issue6, user2, project1.ID, column1.ID) assert.NoError(t, err) // issue 16 belongs to public repo 16 under org 3 issue16 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 16}) - err = issues_model.IssueAssignOrRemoveProject(db.DefaultContext, issue16, user2, project1.ID, column1.ID) + err = issues_model.IssueAssignOrRemoveProject(t.Context(), issue16, user2, project1.ID, column1.ID) assert.NoError(t, err) - projects, err := db.Find[project_model.Project](db.DefaultContext, project_model.SearchOptions{ + projects, err := db.Find[project_model.Project](t.Context(), project_model.SearchOptions{ OwnerID: org3.ID, }) assert.NoError(t, err) @@ -133,7 +133,7 @@ func Test_Projects(t *testing.T) { assert.Equal(t, project1.ID, projects[0].ID) t.Run("Authenticated user", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ Owner: org3.AsUser(), Doer: userAdmin, }) @@ -143,7 +143,7 @@ func Test_Projects(t *testing.T) { }) t.Run("Anonymous user", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ AllPublic: true, }) assert.NoError(t, err) @@ -152,7 +152,7 @@ func Test_Projects(t *testing.T) { }) t.Run("Authenticated user with no permission to the private repo", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ Owner: org3.AsUser(), Doer: user2, }) @@ -165,7 +165,7 @@ func Test_Projects(t *testing.T) { t.Run("Repository projects", func(t *testing.T) { repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - projects, err := db.Find[project_model.Project](db.DefaultContext, project_model.SearchOptions{ + projects, err := db.Find[project_model.Project](t.Context(), project_model.SearchOptions{ RepoID: repo1.ID, }) assert.NoError(t, err) @@ -173,7 +173,7 @@ func Test_Projects(t *testing.T) { assert.EqualValues(t, 1, projects[0].ID) t.Run("Authenticated user", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ RepoIDs: []int64{repo1.ID}, Doer: userAdmin, }) @@ -185,7 +185,7 @@ func Test_Projects(t *testing.T) { }) t.Run("Anonymous user", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ AllPublic: true, }) assert.NoError(t, err) @@ -196,7 +196,7 @@ func Test_Projects(t *testing.T) { }) t.Run("Authenticated user with no permission to the private repo", func(t *testing.T) { - columnIssues, err := LoadIssuesFromProject(db.DefaultContext, projects[0], &issues_model.IssuesOptions{ + columnIssues, err := LoadIssuesFromProject(t.Context(), projects[0], &issues_model.IssuesOptions{ RepoIDs: []int64{repo1.ID}, Doer: user2, }) diff --git a/services/pull/check_test.go b/services/pull/check_test.go index eb66615dcfc..0f392379324 100644 --- a/services/pull/check_test.go +++ b/services/pull/check_test.go @@ -42,7 +42,7 @@ func TestPullRequest_AddToTaskQueue(t *testing.T) { assert.NoError(t, err) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - StartPullRequestCheckImmediately(db.DefaultContext, pr) + StartPullRequestCheckImmediately(t.Context(), pr) assert.Eventually(t, func() bool { pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) diff --git a/services/pull/lfs.go b/services/pull/lfs.go index ed03583d4f2..eb2a08ed8df 100644 --- a/services/pull/lfs.go +++ b/services/pull/lfs.go @@ -11,7 +11,6 @@ import ( "strconv" "sync" - "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/git/pipeline" @@ -40,7 +39,7 @@ func LFSPush(ctx context.Context, tmpBasePath, mergeHeadSHA, mergeBaseSHA string // 6. Take the output of cat-file --batch and check if each file in turn // to see if they're pointers to files in the LFS store associated with // the head repo and add them to the base repo if so - go createLFSMetaObjectsFromCatFileBatch(db.DefaultContext, catFileBatchReader, &wg, pr) + go createLFSMetaObjectsFromCatFileBatch(ctx, catFileBatchReader, &wg, pr) // 5. Take the shas of the blobs and batch read them go pipeline.CatFileBatch(ctx, shasToBatchReader, catFileBatchWriter, &wg, tmpBasePath) diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go index 787910bf760..1c03ab45ae2 100644 --- a/services/pull/pull_test.go +++ b/services/pull/pull_test.go @@ -7,12 +7,10 @@ package pull import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "github.com/stretchr/testify/assert" @@ -41,18 +39,18 @@ func TestPullRequest_GetDefaultMergeMessage_InternalTracker(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) - assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, pr.BaseRepo) + assert.NoError(t, pr.LoadBaseRepo(t.Context())) + gitRepo, err := gitrepo.OpenRepository(t.Context(), pr.BaseRepo) assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, _, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err := GetDefaultMergeMessage(t.Context(), gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from branch2 into master", mergeMessage) pr.BaseRepoID = 1 pr.HeadRepoID = 2 - mergeMessage, _, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err = GetDefaultMergeMessage(t.Context(), gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo1:branch2 into master", mergeMessage) } @@ -71,12 +69,12 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2, BaseRepo: baseRepo}) - assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, pr.BaseRepo) + assert.NoError(t, pr.LoadBaseRepo(t.Context())) + gitRepo, err := gitrepo.OpenRepository(t.Context(), pr.BaseRepo) assert.NoError(t, err) defer gitRepo.Close() - mergeMessage, _, err := GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err := GetDefaultMergeMessage(t.Context(), gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (!3) from branch2 into master", mergeMessage) @@ -85,7 +83,7 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr.HeadRepoID = 2 pr.BaseRepo = nil pr.HeadRepo = nil - mergeMessage, _, err = GetDefaultMergeMessage(db.DefaultContext, gitRepo, pr, "") + mergeMessage, _, err = GetDefaultMergeMessage(t.Context(), gitRepo, pr, "") assert.NoError(t, err) assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo2:branch2 into master", mergeMessage) diff --git a/services/pull/review_test.go b/services/pull/review_test.go index 3bce1e523d7..ddb2c04eaac 100644 --- a/services/pull/review_test.go +++ b/services/pull/review_test.go @@ -6,7 +6,6 @@ package pull_test import ( "testing" - "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -19,11 +18,11 @@ func TestDismissReview(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{}) - assert.NoError(t, pull.LoadIssue(db.DefaultContext)) + assert.NoError(t, pull.LoadIssue(t.Context())) issue := pull.Issue - assert.NoError(t, issue.LoadRepo(db.DefaultContext)) + assert.NoError(t, issue.LoadRepo(t.Context())) reviewer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - review, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{ + review, err := issues_model.CreateReview(t.Context(), issues_model.CreateReviewOptions{ Issue: issue, Reviewer: reviewer, Type: issues_model.ReviewTypeReject, @@ -32,17 +31,17 @@ func TestDismissReview(t *testing.T) { assert.NoError(t, err) issue.IsClosed = true pull.HasMerged = false - assert.NoError(t, issues_model.UpdateIssueCols(db.DefaultContext, issue, "is_closed")) - assert.NoError(t, pull.UpdateCols(db.DefaultContext, "has_merged")) - _, err = pull_service.DismissReview(db.DefaultContext, review.ID, issue.RepoID, "", &user_model.User{}, false, false) + assert.NoError(t, issues_model.UpdateIssueCols(t.Context(), issue, "is_closed")) + assert.NoError(t, pull.UpdateCols(t.Context(), "has_merged")) + _, err = pull_service.DismissReview(t.Context(), review.ID, issue.RepoID, "", &user_model.User{}, false, false) assert.Error(t, err) assert.True(t, pull_service.IsErrDismissRequestOnClosedPR(err)) pull.HasMerged = true pull.Issue.IsClosed = false - assert.NoError(t, issues_model.UpdateIssueCols(db.DefaultContext, issue, "is_closed")) - assert.NoError(t, pull.UpdateCols(db.DefaultContext, "has_merged")) - _, err = pull_service.DismissReview(db.DefaultContext, review.ID, issue.RepoID, "", &user_model.User{}, false, false) + assert.NoError(t, issues_model.UpdateIssueCols(t.Context(), issue, "is_closed")) + assert.NoError(t, pull.UpdateCols(t.Context(), "has_merged")) + _, err = pull_service.DismissReview(t.Context(), review.ID, issue.RepoID, "", &user_model.User{}, false, false) assert.Error(t, err) assert.True(t, pull_service.IsErrDismissRequestOnClosedPR(err)) } diff --git a/services/pull/reviewer_test.go b/services/pull/reviewer_test.go index b106e2e89f5..9fab65ce720 100644 --- a/services/pull/reviewer_test.go +++ b/services/pull/reviewer_test.go @@ -6,7 +6,6 @@ package pull_test import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" pull_service "code.gitea.io/gitea/services/pull" @@ -20,7 +19,7 @@ func TestRepoGetReviewers(t *testing.T) { // test public repo repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - ctx := db.DefaultContext + ctx := t.Context() reviewers, err := pull_service.GetReviewers(ctx, repo1, 2, 0) assert.NoError(t, err) if assert.Len(t, reviewers, 1) { @@ -61,12 +60,12 @@ func TestRepoGetReviewerTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - teams, err := pull_service.GetReviewerTeams(db.DefaultContext, repo2) + teams, err := pull_service.GetReviewerTeams(t.Context(), repo2) assert.NoError(t, err) assert.Empty(t, teams) repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - teams, err = pull_service.GetReviewerTeams(db.DefaultContext, repo3) + teams, err = pull_service.GetReviewerTeams(t.Context(), repo3) assert.NoError(t, err) assert.Len(t, teams, 2) } diff --git a/services/release/release_test.go b/services/release/release_test.go index 36a9f667d69..ef495632a75 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -8,11 +8,9 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/services/attachment" @@ -31,7 +29,7 @@ func TestRelease_Create(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo) assert.NoError(t, err) defer gitRepo.Close() @@ -107,7 +105,7 @@ func TestRelease_Create(t *testing.T) { testPlayload := "testtest" - attach, err := attachment.NewAttachment(db.DefaultContext, &repo_model.Attachment{ + attach, err := attachment.NewAttachment(t.Context(), &repo_model.Attachment{ RepoID: repo.ID, UploaderID: user.ID, Name: "test.txt", @@ -136,7 +134,7 @@ func TestRelease_Update(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo) assert.NoError(t, err) defer gitRepo.Close() @@ -154,13 +152,13 @@ func TestRelease_Update(t *testing.T) { IsPrerelease: false, IsTag: false, }, nil, "")) - release, err := repo_model.GetRelease(db.DefaultContext, repo.ID, "v1.1.1") + release, err := repo_model.GetRelease(t.Context(), repo.ID, "v1.1.1") assert.NoError(t, err) releaseCreatedUnix := release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Note = "Changed note" - assert.NoError(t, UpdateRelease(db.DefaultContext, user, gitRepo, release, nil, nil, nil)) - release, err = repo_model.GetReleaseByID(db.DefaultContext, release.ID) + assert.NoError(t, UpdateRelease(t.Context(), user, gitRepo, release, nil, nil, nil)) + release, err = repo_model.GetReleaseByID(t.Context(), release.ID) assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -178,13 +176,13 @@ func TestRelease_Update(t *testing.T) { IsPrerelease: false, IsTag: false, }, nil, "")) - release, err = repo_model.GetRelease(db.DefaultContext, repo.ID, "v1.2.1") + release, err = repo_model.GetRelease(t.Context(), repo.ID, "v1.2.1") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" - assert.NoError(t, UpdateRelease(db.DefaultContext, user, gitRepo, release, nil, nil, nil)) - release, err = repo_model.GetReleaseByID(db.DefaultContext, release.ID) + assert.NoError(t, UpdateRelease(t.Context(), user, gitRepo, release, nil, nil, nil)) + release, err = repo_model.GetReleaseByID(t.Context(), release.ID) assert.NoError(t, err) assert.Less(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -202,14 +200,14 @@ func TestRelease_Update(t *testing.T) { IsPrerelease: true, IsTag: false, }, nil, "")) - release, err = repo_model.GetRelease(db.DefaultContext, repo.ID, "v1.3.1") + release, err = repo_model.GetRelease(t.Context(), repo.ID, "v1.3.1") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" release.Note = "Changed note" - assert.NoError(t, UpdateRelease(db.DefaultContext, user, gitRepo, release, nil, nil, nil)) - release, err = repo_model.GetReleaseByID(db.DefaultContext, release.ID) + assert.NoError(t, UpdateRelease(t.Context(), user, gitRepo, release, nil, nil, nil)) + release, err = repo_model.GetReleaseByID(t.Context(), release.ID) assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -233,42 +231,42 @@ func TestRelease_Update(t *testing.T) { release.IsDraft = false tagName := release.TagName - assert.NoError(t, UpdateRelease(db.DefaultContext, user, gitRepo, release, nil, nil, nil)) - release, err = repo_model.GetReleaseByID(db.DefaultContext, release.ID) + assert.NoError(t, UpdateRelease(t.Context(), user, gitRepo, release, nil, nil, nil)) + release, err = repo_model.GetReleaseByID(t.Context(), release.ID) assert.NoError(t, err) assert.Equal(t, tagName, release.TagName) // Add new attachments samplePayload := "testtest" - attach, err := attachment.NewAttachment(db.DefaultContext, &repo_model.Attachment{ + attach, err := attachment.NewAttachment(t.Context(), &repo_model.Attachment{ RepoID: repo.ID, UploaderID: user.ID, Name: "test.txt", }, strings.NewReader(samplePayload), int64(len([]byte(samplePayload)))) assert.NoError(t, err) - assert.NoError(t, UpdateRelease(db.DefaultContext, user, gitRepo, release, []string{attach.UUID}, nil, nil)) - assert.NoError(t, repo_model.GetReleaseAttachments(db.DefaultContext, release)) + assert.NoError(t, UpdateRelease(t.Context(), user, gitRepo, release, []string{attach.UUID}, nil, nil)) + assert.NoError(t, repo_model.GetReleaseAttachments(t.Context(), release)) assert.Len(t, release.Attachments, 1) assert.Equal(t, attach.UUID, release.Attachments[0].UUID) assert.Equal(t, release.ID, release.Attachments[0].ReleaseID) assert.Equal(t, attach.Name, release.Attachments[0].Name) // update the attachment name - assert.NoError(t, UpdateRelease(db.DefaultContext, user, gitRepo, release, nil, nil, map[string]string{ + assert.NoError(t, UpdateRelease(t.Context(), user, gitRepo, release, nil, nil, map[string]string{ attach.UUID: "test2.txt", })) release.Attachments = nil - assert.NoError(t, repo_model.GetReleaseAttachments(db.DefaultContext, release)) + assert.NoError(t, repo_model.GetReleaseAttachments(t.Context(), release)) assert.Len(t, release.Attachments, 1) assert.Equal(t, attach.UUID, release.Attachments[0].UUID) assert.Equal(t, release.ID, release.Attachments[0].ReleaseID) assert.Equal(t, "test2.txt", release.Attachments[0].Name) // delete the attachment - assert.NoError(t, UpdateRelease(db.DefaultContext, user, gitRepo, release, nil, []string{attach.UUID}, nil)) + assert.NoError(t, UpdateRelease(t.Context(), user, gitRepo, release, nil, []string{attach.UUID}, nil)) release.Attachments = nil - assert.NoError(t, repo_model.GetReleaseAttachments(db.DefaultContext, release)) + assert.NoError(t, repo_model.GetReleaseAttachments(t.Context(), release)) assert.Empty(t, release.Attachments) } @@ -278,7 +276,7 @@ func TestRelease_createTag(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo) assert.NoError(t, err) defer gitRepo.Close() @@ -296,13 +294,13 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - _, err = createTag(db.DefaultContext, gitRepo, release, "") + _, err = createTag(t.Context(), gitRepo, release, "") assert.NoError(t, err) assert.NotEmpty(t, release.CreatedUnix) releaseCreatedUnix := release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Note = "Changed note" - _, err = createTag(db.DefaultContext, gitRepo, release, "") + _, err = createTag(t.Context(), gitRepo, release, "") assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -320,12 +318,12 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: false, IsTag: false, } - _, err = createTag(db.DefaultContext, gitRepo, release, "") + _, err = createTag(t.Context(), gitRepo, release, "") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" - _, err = createTag(db.DefaultContext, gitRepo, release, "") + _, err = createTag(t.Context(), gitRepo, release, "") assert.NoError(t, err) assert.Less(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) @@ -343,13 +341,13 @@ func TestRelease_createTag(t *testing.T) { IsPrerelease: true, IsTag: false, } - _, err = createTag(db.DefaultContext, gitRepo, release, "") + _, err = createTag(t.Context(), gitRepo, release, "") assert.NoError(t, err) releaseCreatedUnix = release.CreatedUnix time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp release.Title = "Changed title" release.Note = "Changed note" - _, err = createTag(db.DefaultContext, gitRepo, release, "") + _, err = createTag(t.Context(), gitRepo, release, "") assert.NoError(t, err) assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) } @@ -359,6 +357,6 @@ func TestCreateNewTag(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - assert.NoError(t, CreateNewTag(git.DefaultContext, user, repo, "master", "v2.0", + assert.NoError(t, CreateNewTag(t.Context(), user, repo, "master", "v2.0", "v2.0 is released \n\n BUGFIX: .... \n\n 123")) } diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 2bd1c55de48..a17111dfafb 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -17,6 +17,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/optional" repo_module "code.gitea.io/gitea/modules/repository" @@ -28,7 +29,7 @@ import ( ) func deleteFailedAdoptRepository(repoID int64) error { - return db.WithTx(db.DefaultContext, func(ctx context.Context) error { + return db.WithTx(graceful.GetManager().ShutdownContext(), func(ctx context.Context) error { if err := deleteDBRepository(ctx, repoID); err != nil { return fmt.Errorf("deleteDBRepository: %w", err) } diff --git a/services/repository/adopt_test.go b/services/repository/adopt_test.go index 86f586c748f..46f2f484175 100644 --- a/services/repository/adopt_test.go +++ b/services/repository/adopt_test.go @@ -43,7 +43,7 @@ func TestCheckUnadoptedRepositories(t *testing.T) { // Non existent user // unadopted := &unadoptedRepositories{start: 0, end: 100} - err := checkUnadoptedRepositories(db.DefaultContext, "notauser", []string{"repo"}, unadopted) + err := checkUnadoptedRepositories(t.Context(), "notauser", []string{"repo"}, unadopted) assert.NoError(t, err) assert.Empty(t, unadopted.repositories) // @@ -54,14 +54,14 @@ func TestCheckUnadoptedRepositories(t *testing.T) { repoName := "repo2" unadoptedRepoName := "unadopted" unadopted = &unadoptedRepositories{start: 0, end: 100} - err = checkUnadoptedRepositories(db.DefaultContext, userName, []string{repoName, unadoptedRepoName}, unadopted) + err = checkUnadoptedRepositories(t.Context(), userName, []string{repoName, unadoptedRepoName}, unadopted) assert.NoError(t, err) assert.Equal(t, []string{path.Join(userName, unadoptedRepoName)}, unadopted.repositories) // // Existing (adopted) repository is not returned // unadopted = &unadoptedRepositories{start: 0, end: 100} - err = checkUnadoptedRepositories(db.DefaultContext, userName, []string{repoName}, unadopted) + err = checkUnadoptedRepositories(t.Context(), userName, []string{repoName}, unadopted) assert.NoError(t, err) assert.Empty(t, unadopted.repositories) assert.Equal(t, 0, unadopted.index) @@ -76,13 +76,13 @@ func TestListUnadoptedRepositories_ListOptions(t *testing.T) { } opts := db.ListOptions{Page: 1, PageSize: 1} - repoNames, count, err := ListUnadoptedRepositories(db.DefaultContext, "", &opts) + repoNames, count, err := ListUnadoptedRepositories(t.Context(), "", &opts) assert.NoError(t, err) assert.Equal(t, 2, count) assert.Equal(t, unadoptedList[0], repoNames[0]) opts = db.ListOptions{Page: 2, PageSize: 1} - repoNames, count, err = ListUnadoptedRepositories(db.DefaultContext, "", &opts) + repoNames, count, err = ListUnadoptedRepositories(t.Context(), "", &opts) assert.NoError(t, err) assert.Equal(t, 2, count) assert.Equal(t, unadoptedList[1], repoNames[0]) @@ -97,7 +97,7 @@ func TestAdoptRepository(t *testing.T) { destDir := filepath.Join(setting.RepoRootPath, user2.Name, "test-adopt.git") assert.NoError(t, unittest.SyncDirs(filepath.Join(setting.RepoRootPath, user2.Name, "repo1.git"), destDir)) - adoptedRepo, err := AdoptRepository(db.DefaultContext, user2, user2, CreateRepoOptions{Name: "test-adopt"}) + adoptedRepo, err := AdoptRepository(t.Context(), user2, user2, CreateRepoOptions{Name: "test-adopt"}) assert.NoError(t, err) repoTestAdopt := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: "test-adopt"}) assert.Equal(t, "sha1", repoTestAdopt.ObjectFormatName) @@ -113,7 +113,7 @@ func TestAdoptRepository(t *testing.T) { _ = os.RemoveAll(filepath.Join(destDir, "hooks", "update.d")) assert.NoError(t, os.WriteFile(filepath.Join(destDir, "hooks", "update.d"), []byte("tests"), os.ModePerm)) - adoptedRepo, err = AdoptRepository(db.DefaultContext, user2, user2, CreateRepoOptions{Name: "test-adopt"}) + adoptedRepo, err = AdoptRepository(t.Context(), user2, user2, CreateRepoOptions{Name: "test-adopt"}) assert.Error(t, err) assert.Nil(t, adoptedRepo) diff --git a/services/repository/archiver/archiver_test.go b/services/repository/archiver/archiver_test.go index 87324ad38c0..4ba193ccb65 100644 --- a/services/repository/archiver/archiver_test.go +++ b/services/repository/archiver/archiver_test.go @@ -7,7 +7,6 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/services/contexttest" @@ -79,13 +78,13 @@ func TestArchive_Basic(t *testing.T) { inFlight[1] = tgzReq inFlight[2] = secondReq - doArchive(db.DefaultContext, zipReq) - doArchive(db.DefaultContext, tgzReq) - doArchive(db.DefaultContext, secondReq) + doArchive(t.Context(), zipReq) + doArchive(t.Context(), tgzReq) + doArchive(t.Context(), secondReq) // Make sure sending an unprocessed request through doesn't affect the queue // count. - doArchive(db.DefaultContext, zipReq) + doArchive(t.Context(), zipReq) // Sleep two seconds to make sure the queue doesn't change. time.Sleep(2 * time.Second) @@ -100,7 +99,7 @@ func TestArchive_Basic(t *testing.T) { // We still have the other three stalled at completion, waiting to remove // from archiveInProgress. Try to submit this new one before its // predecessor has cleared out of the queue. - doArchive(db.DefaultContext, zipReq2) + doArchive(t.Context(), zipReq2) // Now we'll submit a request and TimedWaitForCompletion twice, before and // after we release it. We should trigger both the timeout and non-timeout @@ -108,7 +107,7 @@ func TestArchive_Basic(t *testing.T) { timedReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, secondCommit+".tar.gz") assert.NoError(t, err) assert.NotNil(t, timedReq) - doArchive(db.DefaultContext, timedReq) + doArchive(t.Context(), timedReq) zipReq2, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit+".zip") assert.NoError(t, err) diff --git a/services/repository/avatar_test.go b/services/repository/avatar_test.go index 2dc5173eec4..6c7b9e6d26f 100644 --- a/services/repository/avatar_test.go +++ b/services/repository/avatar_test.go @@ -9,7 +9,6 @@ import ( "image/png" "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/avatar" @@ -26,7 +25,7 @@ func TestUploadAvatar(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) - err := UploadAvatar(db.DefaultContext, repo, buff.Bytes()) + err := UploadAvatar(t.Context(), repo, buff.Bytes()) assert.NoError(t, err) assert.Equal(t, avatar.HashAvatar(10, buff.Bytes()), repo.Avatar) } @@ -40,7 +39,7 @@ func TestUploadBigAvatar(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) - err := UploadAvatar(db.DefaultContext, repo, buff.Bytes()) + err := UploadAvatar(t.Context(), repo, buff.Bytes()) assert.Error(t, err) } @@ -53,10 +52,10 @@ func TestDeleteAvatar(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) - err := UploadAvatar(db.DefaultContext, repo, buff.Bytes()) + err := UploadAvatar(t.Context(), repo, buff.Bytes()) assert.NoError(t, err) - err = DeleteAvatar(db.DefaultContext, repo) + err = DeleteAvatar(t.Context(), repo) assert.NoError(t, err) assert.Empty(t, repo.Avatar) @@ -65,7 +64,7 @@ func TestDeleteAvatar(t *testing.T) { func TestGenerateAvatar(t *testing.T) { templateRepo := &repo_model.Repository{ID: 10, Avatar: "a"} generateRepo := &repo_model.Repository{ID: 11} - _ = generateAvatar(db.DefaultContext, templateRepo, generateRepo) + _ = generateAvatar(t.Context(), templateRepo, generateRepo) assert.NotEmpty(t, generateRepo.Avatar) assert.NotEqual(t, templateRepo.Avatar, generateRepo.Avatar) } diff --git a/services/repository/collaboration_test.go b/services/repository/collaboration_test.go index 2b9a5d0b8ba..5e33c50366c 100644 --- a/services/repository/collaboration_test.go +++ b/services/repository/collaboration_test.go @@ -6,7 +6,6 @@ package repository import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -20,9 +19,9 @@ func TestRepository_AddCollaborator(t *testing.T) { testSuccess := func(repoID, userID int64) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) - assert.NoError(t, repo.LoadOwner(db.DefaultContext)) + assert.NoError(t, repo.LoadOwner(t.Context())) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}) - assert.NoError(t, AddOrUpdateCollaborator(db.DefaultContext, repo, user, perm.AccessModeWrite)) + assert.NoError(t, AddOrUpdateCollaborator(t.Context(), repo, user, perm.AccessModeWrite)) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID}) } testSuccess(1, 4) @@ -36,11 +35,11 @@ func TestRepository_DeleteCollaboration(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) - assert.NoError(t, repo.LoadOwner(db.DefaultContext)) - assert.NoError(t, DeleteCollaboration(db.DefaultContext, repo, user)) + assert.NoError(t, repo.LoadOwner(t.Context())) + assert.NoError(t, DeleteCollaboration(t.Context(), repo, user)) unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: user.ID}) - assert.NoError(t, DeleteCollaboration(db.DefaultContext, repo, user)) + assert.NoError(t, DeleteCollaboration(t.Context(), repo, user)) unittest.AssertNotExistsBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: user.ID}) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) diff --git a/services/repository/contributors_graph_test.go b/services/repository/contributors_graph_test.go index 7d32b1c9316..efdecf4b813 100644 --- a/services/repository/contributors_graph_test.go +++ b/services/repository/contributors_graph_test.go @@ -7,7 +7,6 @@ import ( "slices" "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/cache" @@ -20,7 +19,7 @@ func TestRepository_ContributorsGraph(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - assert.NoError(t, repo.LoadOwner(db.DefaultContext)) + assert.NoError(t, repo.LoadOwner(t.Context())) mockCache, err := cache.NewStringCache(setting.Cache{}) assert.NoError(t, err) diff --git a/services/repository/create.go b/services/repository/create.go index bed02e5d7e9..da31ee41211 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/options" repo_module "code.gitea.io/gitea/modules/repository" @@ -459,7 +460,7 @@ func createRepositoryInDB(ctx context.Context, doer, u *user_model.User, repo *r } func cleanupRepository(repoID int64) { - if errDelete := DeleteRepositoryDirectly(db.DefaultContext, repoID); errDelete != nil { + if errDelete := DeleteRepositoryDirectly(graceful.GetManager().ShutdownContext(), repoID); errDelete != nil { log.Error("cleanupRepository failed: %v", errDelete) // add system notice if err := system_model.CreateRepositoryNotice("DeleteRepositoryDirectly failed when cleanup repository: %v", errDelete); err != nil { @@ -469,7 +470,7 @@ func cleanupRepository(repoID int64) { } func updateGitRepoAfterCreate(ctx context.Context, repo *repo_model.Repository) error { - if err := checkDaemonExportOK(ctx, repo); err != nil { + if err := CheckDaemonExportOK(ctx, repo); err != nil { return fmt.Errorf("checkDaemonExportOK: %w", err) } diff --git a/services/repository/create_test.go b/services/repository/create_test.go index fe464c1441c..b8c2ea59ddb 100644 --- a/services/repository/create_test.go +++ b/services/repository/create_test.go @@ -7,11 +7,9 @@ import ( "os" "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/util" "github.com/stretchr/testify/assert" @@ -23,7 +21,7 @@ func TestCreateRepositoryDirectly(t *testing.T) { // a successful creating repository user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - createdRepo, err := CreateRepositoryDirectly(git.DefaultContext, user2, user2, CreateRepoOptions{ + createdRepo, err := CreateRepositoryDirectly(t.Context(), user2, user2, CreateRepoOptions{ Name: "created-repo", }, true) assert.NoError(t, err) @@ -35,14 +33,14 @@ func TestCreateRepositoryDirectly(t *testing.T) { unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: user2.Name, Name: createdRepo.Name}) - err = DeleteRepositoryDirectly(db.DefaultContext, createdRepo.ID) + err = DeleteRepositoryDirectly(t.Context(), createdRepo.ID) assert.NoError(t, err) // a failed creating because some mock data // create the repository directory so that the creation will fail after database record created. assert.NoError(t, os.MkdirAll(repo_model.RepoPath(user2.Name, createdRepo.Name), os.ModePerm)) - createdRepo2, err := CreateRepositoryDirectly(db.DefaultContext, user2, user2, CreateRepoOptions{ + createdRepo2, err := CreateRepositoryDirectly(t.Context(), user2, user2, CreateRepoOptions{ Name: "created-repo", }, true) assert.Nil(t, createdRepo2) diff --git a/services/repository/delete.go b/services/repository/delete.go index c48d6e1d56e..65dfc2a3b76 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/models/webhook" actions_module "code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/storage" @@ -309,8 +310,7 @@ func DeleteRepositoryDirectly(ctx context.Context, repoID int64, ignoreOrgTeams // Remove repository files. if err := gitrepo.DeleteRepository(ctx, repo); err != nil { desc := fmt.Sprintf("Delete repository files [%s]: %v", repo.FullName(), err) - // Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled - if err = system_model.CreateNotice(db.DefaultContext, system_model.NoticeRepository, desc); err != nil { + if err = system_model.CreateNotice(graceful.GetManager().ShutdownContext(), system_model.NoticeRepository, desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } } diff --git a/services/repository/delete_test.go b/services/repository/delete_test.go index 869b8af11d5..f06373f24ab 100644 --- a/services/repository/delete_test.go +++ b/services/repository/delete_test.go @@ -6,7 +6,6 @@ package repository_test import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -21,7 +20,7 @@ func TestTeam_HasRepository(t *testing.T) { test := func(teamID, repoID int64, expected bool) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) - assert.Equal(t, expected, repo_service.HasRepository(db.DefaultContext, team, repoID)) + assert.Equal(t, expected, repo_service.HasRepository(t.Context(), team, repoID)) } test(1, 1, false) test(1, 3, true) @@ -37,7 +36,7 @@ func TestTeam_RemoveRepository(t *testing.T) { testSuccess := func(teamID, repoID int64) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) - assert.NoError(t, repo_service.RemoveRepositoryFromTeam(db.DefaultContext, team, repoID)) + assert.NoError(t, repo_service.RemoveRepositoryFromTeam(t.Context(), team, repoID)) unittest.AssertNotExistsBean(t, &organization.TeamRepo{TeamID: teamID, RepoID: repoID}) unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID}, &repo_model.Repository{ID: repoID}) } @@ -51,5 +50,5 @@ func TestDeleteOwnerRepositoriesDirectly(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, repo_service.DeleteOwnerRepositoriesDirectly(db.DefaultContext, user)) + assert.NoError(t, repo_service.DeleteOwnerRepositoriesDirectly(t.Context(), user)) } diff --git a/services/repository/fork_test.go b/services/repository/fork_test.go index 5375f790282..680a7f3207e 100644 --- a/services/repository/fork_test.go +++ b/services/repository/fork_test.go @@ -7,11 +7,9 @@ import ( "os" "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/util" @@ -26,7 +24,7 @@ func TestForkRepository(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 13}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) - fork, err := ForkRepository(git.DefaultContext, user, user, ForkRepoOptions{ + fork, err := ForkRepository(t.Context(), user, user, ForkRepoOptions{ BaseRepo: repo, Name: "test", Description: "test", @@ -42,7 +40,7 @@ func TestForkRepository(t *testing.T) { defer test.MockVariableValue(&setting.Repository.AllowForkWithoutMaximumLimit, false)() // user has reached maximum limit of repositories user.MaxRepoCreation = 0 - fork2, err := ForkRepository(git.DefaultContext, user, user, ForkRepoOptions{ + fork2, err := ForkRepository(t.Context(), user, user, ForkRepoOptions{ BaseRepo: repo, Name: "test", Description: "test", @@ -58,7 +56,7 @@ func TestForkRepositoryCleanup(t *testing.T) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo10 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}) - fork, err := ForkRepository(git.DefaultContext, user2, user2, ForkRepoOptions{ + fork, err := ForkRepository(t.Context(), user2, user2, ForkRepoOptions{ BaseRepo: repo10, Name: "test", }) @@ -69,14 +67,14 @@ func TestForkRepositoryCleanup(t *testing.T) { assert.NoError(t, err) assert.True(t, exist) - err = DeleteRepositoryDirectly(db.DefaultContext, fork.ID) + err = DeleteRepositoryDirectly(t.Context(), fork.ID) assert.NoError(t, err) // a failed creating because some mock data // create the repository directory so that the creation will fail after database record created. assert.NoError(t, os.MkdirAll(repo_model.RepoPath(user2.Name, "test"), os.ModePerm)) - fork2, err := ForkRepository(db.DefaultContext, user2, user2, ForkRepoOptions{ + fork2, err := ForkRepository(t.Context(), user2, user2, ForkRepoOptions{ BaseRepo: repo10, Name: "test", }) diff --git a/services/repository/gitgraph/graph_test.go b/services/repository/gitgraph/graph_test.go index 93fa1aec6a3..eda499840b3 100644 --- a/services/repository/gitgraph/graph_test.go +++ b/services/repository/gitgraph/graph_test.go @@ -16,7 +16,7 @@ import ( ) func BenchmarkGetCommitGraph(b *testing.B) { - currentRepo, err := git.OpenRepository(git.DefaultContext, ".") + currentRepo, err := git.OpenRepository(b.Context(), ".") if err != nil || currentRepo == nil { b.Error("Could not open repository") } diff --git a/services/repository/lfs_test.go b/services/repository/lfs_test.go index 78ff8c853ee..7fb202f42d6 100644 --- a/services/repository/lfs_test.go +++ b/services/repository/lfs_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -27,7 +26,7 @@ func TestGarbageCollectLFSMetaObjects(t *testing.T) { err := storage.Init() assert.NoError(t, err) - repo, err := repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, "user2", "repo1") + repo, err := repo_model.GetRepositoryByOwnerAndName(t.Context(), "user2", "repo1") assert.NoError(t, err) // add lfs object @@ -43,7 +42,7 @@ func TestGarbageCollectLFSMetaObjects(t *testing.T) { assert.NoError(t, err) // lfs meta has been deleted - _, err = git_model.GetLFSMetaObjectByOid(db.DefaultContext, repo.ID, lfsOid) + _, err = git_model.GetLFSMetaObjectByOid(t.Context(), repo.ID, lfsOid) assert.ErrorIs(t, err, git_model.ErrLFSObjectNotExist) } @@ -51,7 +50,7 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string pointer, err := lfs.GeneratePointer(bytes.NewReader(*content)) assert.NoError(t, err) - _, err = git_model.NewLFSMetaObject(db.DefaultContext, repositoryID, pointer) + _, err = git_model.NewLFSMetaObject(t.Context(), repositoryID, pointer) assert.NoError(t, err) contentStore := lfs.NewContentStore() exist, err := contentStore.Exists(pointer) diff --git a/services/repository/repo_team_test.go b/services/repository/repo_team_test.go index 70b1b47d0af..1139d06cf87 100644 --- a/services/repository/repo_team_test.go +++ b/services/repository/repo_team_test.go @@ -6,7 +6,6 @@ package repository import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -20,7 +19,7 @@ func TestTeam_AddRepository(t *testing.T) { testSuccess := func(teamID, repoID int64) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: teamID}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) - assert.NoError(t, TeamAddRepository(db.DefaultContext, team, repo)) + assert.NoError(t, TeamAddRepository(t.Context(), team, repo)) unittest.AssertExistsAndLoadBean(t, &organization.TeamRepo{TeamID: teamID, RepoID: repoID}) unittest.CheckConsistencyFor(t, &organization.Team{ID: teamID}, &repo_model.Repository{ID: repoID}) } @@ -29,6 +28,6 @@ func TestTeam_AddRepository(t *testing.T) { team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - assert.Error(t, TeamAddRepository(db.DefaultContext, team, repo)) + assert.Error(t, TeamAddRepository(t.Context(), team, repo)) unittest.CheckConsistencyFor(t, &organization.Team{ID: 1}, &repo_model.Repository{ID: 1}) } diff --git a/services/repository/repository.go b/services/repository/repository.go index e574dc6c018..df5462bf5ae 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -142,7 +142,7 @@ func MakeRepoPublic(ctx context.Context, repo *repo_model.Repository) (err error } // Create/Remove git-daemon-export-ok for git-daemon... - if err := checkDaemonExportOK(ctx, repo); err != nil { + if err := CheckDaemonExportOK(ctx, repo); err != nil { return err } @@ -197,7 +197,7 @@ func MakeRepoPrivate(ctx context.Context, repo *repo_model.Repository) (err erro } // Create/Remove git-daemon-export-ok for git-daemon... - if err := checkDaemonExportOK(ctx, repo); err != nil { + if err := CheckDaemonExportOK(ctx, repo); err != nil { return err } @@ -243,8 +243,8 @@ func LinkedRepository(ctx context.Context, a *repo_model.Attachment) (*repo_mode return nil, -1, nil } -// checkDaemonExportOK creates/removes git-daemon-export-ok for git-daemon... -func checkDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error { +// CheckDaemonExportOK creates/removes git-daemon-export-ok for git-daemon... +func CheckDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error { if err := repo.LoadOwner(ctx); err != nil { return err } @@ -314,7 +314,7 @@ func updateRepository(ctx context.Context, repo *repo_model.Repository, visibili } // Create/Remove git-daemon-export-ok for git-daemon... - if err := checkDaemonExportOK(ctx, repo); err != nil { + if err := CheckDaemonExportOK(ctx, repo); err != nil { return err } diff --git a/services/repository/repository_test.go b/services/repository/repository_test.go index 8f9fdf8fa13..ba02e7601cd 100644 --- a/services/repository/repository_test.go +++ b/services/repository/repository_test.go @@ -30,9 +30,9 @@ func TestLinkedRepository(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - attach, err := repo_model.GetAttachmentByID(db.DefaultContext, tc.attachID) + attach, err := repo_model.GetAttachmentByID(t.Context(), tc.attachID) assert.NoError(t, err) - repo, unitType, err := LinkedRepository(db.DefaultContext, attach) + repo, unitType, err := LinkedRepository(t.Context(), attach) assert.NoError(t, err) if tc.expectedRepo != nil { assert.Equal(t, tc.expectedRepo.ID, repo.ID) @@ -46,17 +46,17 @@ func TestUpdateRepositoryVisibilityChanged(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // Get sample repo and change visibility - repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 9) + repo, err := repo_model.GetRepositoryByID(t.Context(), 9) assert.NoError(t, err) repo.IsPrivate = true // Update it - err = updateRepository(db.DefaultContext, repo, true) + err = updateRepository(t.Context(), repo, true) assert.NoError(t, err) // Check visibility of action has become private act := activities_model.Action{} - _, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act) + _, err = db.GetEngine(t.Context()).ID(3).Get(&act) assert.NoError(t, err) assert.True(t, act.IsPrivate) diff --git a/services/repository/transfer_test.go b/services/repository/transfer_test.go index 80a073e9f91..8d73fef7f4b 100644 --- a/services/repository/transfer_test.go +++ b/services/repository/transfer_test.go @@ -8,7 +8,6 @@ import ( "testing" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" @@ -39,10 +38,10 @@ func TestTransferOwnership(t *testing.T) { doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - assert.NoError(t, repo.LoadOwner(db.DefaultContext)) + assert.NoError(t, repo.LoadOwner(t.Context())) repoTransfer := unittest.AssertExistsAndLoadBean(t, &repo_model.RepoTransfer{ID: 1}) - assert.NoError(t, repoTransfer.LoadAttributes(db.DefaultContext)) - assert.NoError(t, AcceptTransferOwnership(db.DefaultContext, repo, doer)) + assert.NoError(t, repoTransfer.LoadAttributes(t.Context())) + assert.NoError(t, AcceptTransferOwnership(t.Context(), repo, doer)) transferredRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) assert.EqualValues(t, 1, transferredRepo.OwnerID) // repo_transfer.yml id=1 @@ -70,15 +69,15 @@ func TestStartRepositoryTransferSetPermission(t *testing.T) { doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) recipient := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - assert.NoError(t, repo.LoadOwner(db.DefaultContext)) + assert.NoError(t, repo.LoadOwner(t.Context())) - hasAccess, err := access_model.HasAnyUnitAccess(db.DefaultContext, recipient.ID, repo) + hasAccess, err := access_model.HasAnyUnitAccess(t.Context(), recipient.ID, repo) assert.NoError(t, err) assert.False(t, hasAccess) - assert.NoError(t, StartRepositoryTransfer(db.DefaultContext, doer, recipient, repo, nil)) + assert.NoError(t, StartRepositoryTransfer(t.Context(), doer, recipient, repo, nil)) - hasAccess, err = access_model.HasAnyUnitAccess(db.DefaultContext, recipient.ID, repo) + hasAccess, err = access_model.HasAnyUnitAccess(t.Context(), recipient.ID, repo) assert.NoError(t, err) assert.True(t, hasAccess) @@ -91,41 +90,41 @@ func TestRepositoryTransfer(t *testing.T) { doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) - transfer, err := repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo) + transfer, err := repo_model.GetPendingRepositoryTransfer(t.Context(), repo) assert.NoError(t, err) assert.NotNil(t, transfer) // Cancel transfer - assert.NoError(t, CancelRepositoryTransfer(db.DefaultContext, transfer, doer)) + assert.NoError(t, CancelRepositoryTransfer(t.Context(), transfer, doer)) - transfer, err = repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo) + transfer, err = repo_model.GetPendingRepositoryTransfer(t.Context(), repo) assert.Error(t, err) assert.Nil(t, transfer) assert.True(t, repo_model.IsErrNoPendingTransfer(err)) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, repo_model.CreatePendingRepositoryTransfer(db.DefaultContext, doer, user2, repo.ID, nil)) + assert.NoError(t, repo_model.CreatePendingRepositoryTransfer(t.Context(), doer, user2, repo.ID, nil)) - transfer, err = repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo) + transfer, err = repo_model.GetPendingRepositoryTransfer(t.Context(), repo) assert.NoError(t, err) - assert.NoError(t, transfer.LoadAttributes(db.DefaultContext)) + assert.NoError(t, transfer.LoadAttributes(t.Context())) assert.Equal(t, "user2", transfer.Recipient.Name) org6 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // Only transfer can be started at any given time - err = repo_model.CreatePendingRepositoryTransfer(db.DefaultContext, doer, org6, repo.ID, nil) + err = repo_model.CreatePendingRepositoryTransfer(t.Context(), doer, org6, repo.ID, nil) assert.Error(t, err) assert.True(t, repo_model.IsErrRepoTransferInProgress(err)) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) // Unknown user, transfer non-existent transfer repo id = 2 - err = repo_model.CreatePendingRepositoryTransfer(db.DefaultContext, doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo2.ID, nil) + err = repo_model.CreatePendingRepositoryTransfer(t.Context(), doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo2.ID, nil) assert.Error(t, err) // Reject transfer - err = RejectRepositoryTransfer(db.DefaultContext, repo2, doer) + err = RejectRepositoryTransfer(t.Context(), repo2, doer) assert.True(t, repo_model.IsErrNoPendingTransfer(err)) } @@ -139,29 +138,29 @@ func TestRepositoryTransferRejection(t *testing.T) { doerAdmin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 5}) - transfer, err := repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo) + transfer, err := repo_model.GetPendingRepositoryTransfer(t.Context(), repo) require.NoError(t, err) require.NotNil(t, transfer) - require.NoError(t, transfer.LoadRecipient(db.DefaultContext)) + require.NoError(t, transfer.LoadRecipient(t.Context())) require.True(t, doerAdmin.CanCreateRepoIn(transfer.Recipient)) // admin is not subject to limits // Administrator should not be affected by the limits so transfer should be successful - assert.NoError(t, AcceptTransferOwnership(db.DefaultContext, repo, doerAdmin)) + assert.NoError(t, AcceptTransferOwnership(t.Context(), repo, doerAdmin)) // Non admin user case doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10}) repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 21}) - transfer, err = repo_model.GetPendingRepositoryTransfer(db.DefaultContext, repo) + transfer, err = repo_model.GetPendingRepositoryTransfer(t.Context(), repo) require.NoError(t, err) require.NotNil(t, transfer) - require.NoError(t, transfer.LoadRecipient(db.DefaultContext)) + require.NoError(t, transfer.LoadRecipient(t.Context())) require.False(t, doer.CanCreateRepoIn(transfer.Recipient)) // regular user is subject to limits // Cannot accept because of the limit - err = AcceptTransferOwnership(db.DefaultContext, repo, doer) + err = AcceptTransferOwnership(t.Context(), repo, doer) assert.Error(t, err) assert.True(t, IsRepositoryLimitReached(err)) } diff --git a/services/task/task.go b/services/task/task.go index ee5fa1f348f..86cf6a041fd 100644 --- a/services/task/task.go +++ b/services/task/task.go @@ -9,7 +9,6 @@ import ( "fmt" admin_model "code.gitea.io/gitea/models/admin" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/graceful" @@ -50,7 +49,7 @@ func Init() error { func handler(items ...*admin_model.Task) []*admin_model.Task { for _, task := range items { - if err := Run(db.DefaultContext, task); err != nil { + if err := Run(graceful.GetManager().ShutdownContext(), task); err != nil { log.Error("Run task failed: %v", err) } } diff --git a/services/uinotification/notify.go b/services/uinotification/notify.go index be5f7019a2e..dd3f1557c64 100644 --- a/services/uinotification/notify.go +++ b/services/uinotification/notify.go @@ -52,7 +52,7 @@ func NewNotifier() notify_service.Notifier { func handler(items ...issueNotificationOpts) []issueNotificationOpts { for _, opts := range items { - if err := activities_model.CreateOrUpdateIssueNotifications(db.DefaultContext, opts.IssueID, opts.CommentID, opts.NotificationAuthorID, opts.ReceiverID); err != nil { + if err := activities_model.CreateOrUpdateIssueNotifications(graceful.GetManager().ShutdownContext(), opts.IssueID, opts.CommentID, opts.NotificationAuthorID, opts.ReceiverID); err != nil { log.Error("Was unable to create issue notification: %v", err) } } diff --git a/services/user/block_test.go b/services/user/block_test.go index aec3e03cf37..5dc6c1210de 100644 --- a/services/user/block_test.go +++ b/services/user/block_test.go @@ -6,7 +6,6 @@ package user import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -23,23 +22,23 @@ func TestCanBlockUser(t *testing.T) { org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // Doer can't self block - assert.False(t, CanBlockUser(db.DefaultContext, user1, user2, user1)) + assert.False(t, CanBlockUser(t.Context(), user1, user2, user1)) // Blocker can't be blockee - assert.False(t, CanBlockUser(db.DefaultContext, user1, user2, user2)) + assert.False(t, CanBlockUser(t.Context(), user1, user2, user2)) // Can't block already blocked user - assert.False(t, CanBlockUser(db.DefaultContext, user1, user2, user29)) + assert.False(t, CanBlockUser(t.Context(), user1, user2, user29)) // Blockee can't be an organization - assert.False(t, CanBlockUser(db.DefaultContext, user1, user2, org3)) + assert.False(t, CanBlockUser(t.Context(), user1, user2, org3)) // Doer must be blocker or admin - assert.False(t, CanBlockUser(db.DefaultContext, user2, user4, user29)) + assert.False(t, CanBlockUser(t.Context(), user2, user4, user29)) // Organization can't block a member - assert.False(t, CanBlockUser(db.DefaultContext, user1, org3, user4)) + assert.False(t, CanBlockUser(t.Context(), user1, org3, user4)) // Doer must be organization owner or admin if blocker is an organization - assert.False(t, CanBlockUser(db.DefaultContext, user4, org3, user2)) + assert.False(t, CanBlockUser(t.Context(), user4, org3, user2)) - assert.True(t, CanBlockUser(db.DefaultContext, user1, user2, user4)) - assert.True(t, CanBlockUser(db.DefaultContext, user2, user2, user4)) - assert.True(t, CanBlockUser(db.DefaultContext, user2, org3, user29)) + assert.True(t, CanBlockUser(t.Context(), user1, user2, user4)) + assert.True(t, CanBlockUser(t.Context(), user2, user2, user4)) + assert.True(t, CanBlockUser(t.Context(), user2, org3, user29)) } func TestCanUnblockUser(t *testing.T) { @@ -52,15 +51,15 @@ func TestCanUnblockUser(t *testing.T) { org17 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 17}) // Doer can't self unblock - assert.False(t, CanUnblockUser(db.DefaultContext, user1, user2, user1)) + assert.False(t, CanUnblockUser(t.Context(), user1, user2, user1)) // Can't unblock not blocked user - assert.False(t, CanUnblockUser(db.DefaultContext, user1, user2, user28)) + assert.False(t, CanUnblockUser(t.Context(), user1, user2, user28)) // Doer must be blocker or admin - assert.False(t, CanUnblockUser(db.DefaultContext, user28, user2, user29)) + assert.False(t, CanUnblockUser(t.Context(), user28, user2, user29)) // Doer must be organization owner or admin if blocker is an organization - assert.False(t, CanUnblockUser(db.DefaultContext, user2, org17, user28)) + assert.False(t, CanUnblockUser(t.Context(), user2, org17, user28)) - assert.True(t, CanUnblockUser(db.DefaultContext, user1, user2, user29)) - assert.True(t, CanUnblockUser(db.DefaultContext, user2, user2, user29)) - assert.True(t, CanUnblockUser(db.DefaultContext, user1, org17, user28)) + assert.True(t, CanUnblockUser(t.Context(), user1, user2, user29)) + assert.True(t, CanUnblockUser(t.Context(), user2, user2, user29)) + assert.True(t, CanUnblockUser(t.Context(), user1, org17, user28)) } diff --git a/services/user/email_test.go b/services/user/email_test.go index b40f86b6a68..78770633d20 100644 --- a/services/user/email_test.go +++ b/services/user/email_test.go @@ -6,7 +6,6 @@ package user import ( "testing" - "code.gitea.io/gitea/models/db" organization_model "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -21,23 +20,23 @@ func TestAdminAddOrSetPrimaryEmailAddress(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 27}) - emails, err := user_model.GetEmailAddresses(db.DefaultContext, user.ID) + emails, err := user_model.GetEmailAddresses(t.Context(), user.ID) assert.NoError(t, err) assert.Len(t, emails, 1) - primary, err := user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) + primary, err := user_model.GetPrimaryEmailAddressOfUser(t.Context(), user.ID) assert.NoError(t, err) assert.NotEqual(t, "new-primary@example.com", primary.Email) assert.Equal(t, user.Email, primary.Email) - assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(db.DefaultContext, user, "new-primary@example.com")) + assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(t.Context(), user, "new-primary@example.com")) - primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) + primary, err = user_model.GetPrimaryEmailAddressOfUser(t.Context(), user.ID) assert.NoError(t, err) assert.Equal(t, "new-primary@example.com", primary.Email) assert.Equal(t, user.Email, primary.Email) - emails, err = user_model.GetEmailAddresses(db.DefaultContext, user.ID) + emails, err = user_model.GetEmailAddresses(t.Context(), user.ID) assert.NoError(t, err) assert.Len(t, emails, 2) @@ -46,21 +45,21 @@ func TestAdminAddOrSetPrimaryEmailAddress(t *testing.T) { setting.Service.EmailDomainAllowList = []glob.Glob{} }() - assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(db.DefaultContext, user, "new-primary2@example2.com")) + assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(t.Context(), user, "new-primary2@example2.com")) - primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) + primary, err = user_model.GetPrimaryEmailAddressOfUser(t.Context(), user.ID) assert.NoError(t, err) assert.Equal(t, "new-primary2@example2.com", primary.Email) assert.Equal(t, user.Email, primary.Email) - assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(db.DefaultContext, user, "user27@example.com")) + assert.NoError(t, AdminAddOrSetPrimaryEmailAddress(t.Context(), user, "user27@example.com")) - primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) + primary, err = user_model.GetPrimaryEmailAddressOfUser(t.Context(), user.ID) assert.NoError(t, err) assert.Equal(t, "user27@example.com", primary.Email) assert.Equal(t, user.Email, primary.Email) - emails, err = user_model.GetEmailAddresses(db.DefaultContext, user.ID) + emails, err = user_model.GetEmailAddresses(t.Context(), user.ID) assert.NoError(t, err) assert.Len(t, emails, 3) } @@ -71,27 +70,27 @@ func TestReplacePrimaryEmailAddress(t *testing.T) { t.Run("User", func(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 13}) - emails, err := user_model.GetEmailAddresses(db.DefaultContext, user.ID) + emails, err := user_model.GetEmailAddresses(t.Context(), user.ID) assert.NoError(t, err) assert.Len(t, emails, 1) - primary, err := user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) + primary, err := user_model.GetPrimaryEmailAddressOfUser(t.Context(), user.ID) assert.NoError(t, err) assert.NotEqual(t, "primary-13@example.com", primary.Email) assert.Equal(t, user.Email, primary.Email) - assert.NoError(t, ReplacePrimaryEmailAddress(db.DefaultContext, user, "primary-13@example.com")) + assert.NoError(t, ReplacePrimaryEmailAddress(t.Context(), user, "primary-13@example.com")) - primary, err = user_model.GetPrimaryEmailAddressOfUser(db.DefaultContext, user.ID) + primary, err = user_model.GetPrimaryEmailAddressOfUser(t.Context(), user.ID) assert.NoError(t, err) assert.Equal(t, "primary-13@example.com", primary.Email) assert.Equal(t, user.Email, primary.Email) - emails, err = user_model.GetEmailAddresses(db.DefaultContext, user.ID) + emails, err = user_model.GetEmailAddresses(t.Context(), user.ID) assert.NoError(t, err) assert.Len(t, emails, 1) - assert.NoError(t, ReplacePrimaryEmailAddress(db.DefaultContext, user, "primary-13@example.com")) + assert.NoError(t, ReplacePrimaryEmailAddress(t.Context(), user, "primary-13@example.com")) }) t.Run("Organization", func(t *testing.T) { @@ -99,7 +98,7 @@ func TestReplacePrimaryEmailAddress(t *testing.T) { assert.Equal(t, "org3@example.com", org.Email) - assert.NoError(t, ReplacePrimaryEmailAddress(db.DefaultContext, org.AsUser(), "primary-org@example.com")) + assert.NoError(t, ReplacePrimaryEmailAddress(t.Context(), org.AsUser(), "primary-org@example.com")) assert.Equal(t, "primary-org@example.com", org.Email) }) @@ -110,13 +109,13 @@ func TestAddEmailAddresses(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.Error(t, AddEmailAddresses(db.DefaultContext, user, []string{" invalid email "})) + assert.Error(t, AddEmailAddresses(t.Context(), user, []string{" invalid email "})) emails := []string{"user1234@example.com", "user5678@example.com"} - assert.NoError(t, AddEmailAddresses(db.DefaultContext, user, emails)) + assert.NoError(t, AddEmailAddresses(t.Context(), user, emails)) - err := AddEmailAddresses(db.DefaultContext, user, emails) + err := AddEmailAddresses(t.Context(), user, emails) assert.Error(t, err) assert.True(t, user_model.IsErrEmailAlreadyUsed(err)) } @@ -128,16 +127,16 @@ func TestDeleteEmailAddresses(t *testing.T) { emails := []string{"user2-2@example.com"} - err := DeleteEmailAddresses(db.DefaultContext, user, emails) + err := DeleteEmailAddresses(t.Context(), user, emails) assert.NoError(t, err) - err = DeleteEmailAddresses(db.DefaultContext, user, emails) + err = DeleteEmailAddresses(t.Context(), user, emails) assert.Error(t, err) assert.True(t, user_model.IsErrEmailAddressNotExist(err)) emails = []string{"user2@example.com"} - err = DeleteEmailAddresses(db.DefaultContext, user, emails) + err = DeleteEmailAddresses(t.Context(), user, emails) assert.Error(t, err) assert.True(t, user_model.IsErrPrimaryEmailCannotDelete(err)) } diff --git a/services/user/update_test.go b/services/user/update_test.go index 27513e80409..b81ac95783d 100644 --- a/services/user/update_test.go +++ b/services/user/update_test.go @@ -6,7 +6,6 @@ package user import ( "testing" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" password_module "code.gitea.io/gitea/modules/auth/password" @@ -21,11 +20,11 @@ func TestUpdateUser(t *testing.T) { admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - assert.Error(t, UpdateUser(db.DefaultContext, admin, &UpdateOptions{ + assert.Error(t, UpdateUser(t.Context(), admin, &UpdateOptions{ IsAdmin: UpdateOptionFieldFromValue(false), })) - assert.NoError(t, UpdateUser(db.DefaultContext, admin, &UpdateOptions{ + assert.NoError(t, UpdateUser(t.Context(), admin, &UpdateOptions{ IsAdmin: UpdateOptionFieldFromSync(false), })) @@ -52,7 +51,7 @@ func TestUpdateUser(t *testing.T) { EmailNotificationsPreference: optional.Some("disabled"), SetLastLogin: true, } - assert.NoError(t, UpdateUser(db.DefaultContext, user, opts)) + assert.NoError(t, UpdateUser(t.Context(), user, opts)) assert.Equal(t, opts.KeepEmailPrivate.Value(), user.KeepEmailPrivate) assert.Equal(t, opts.FullName.Value(), user.FullName) @@ -100,12 +99,12 @@ func TestUpdateAuth(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 28}) userCopy := *user - assert.NoError(t, UpdateAuth(db.DefaultContext, user, &UpdateAuthOptions{ + assert.NoError(t, UpdateAuth(t.Context(), user, &UpdateAuthOptions{ LoginName: optional.Some("new-login"), })) assert.Equal(t, "new-login", user.LoginName) - assert.NoError(t, UpdateAuth(db.DefaultContext, user, &UpdateAuthOptions{ + assert.NoError(t, UpdateAuth(t.Context(), user, &UpdateAuthOptions{ Password: optional.Some("%$DRZUVB576tfzgu"), MustChangePassword: optional.Some(true), })) @@ -113,12 +112,12 @@ func TestUpdateAuth(t *testing.T) { assert.NotEqual(t, userCopy.Passwd, user.Passwd) assert.NotEqual(t, userCopy.Salt, user.Salt) - assert.NoError(t, UpdateAuth(db.DefaultContext, user, &UpdateAuthOptions{ + assert.NoError(t, UpdateAuth(t.Context(), user, &UpdateAuthOptions{ ProhibitLogin: optional.Some(true), })) assert.True(t, user.ProhibitLogin) - assert.ErrorIs(t, UpdateAuth(db.DefaultContext, user, &UpdateAuthOptions{ + assert.ErrorIs(t, UpdateAuth(t.Context(), user, &UpdateAuthOptions{ Password: optional.Some("aaaa"), }), password_module.ErrMinLength) } diff --git a/services/user/user_test.go b/services/user/user_test.go index 28a0df8628f..48852b4cb9a 100644 --- a/services/user/user_test.go +++ b/services/user/user_test.go @@ -32,24 +32,24 @@ func TestDeleteUser(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}) ownedRepos := make([]*repo_model.Repository, 0, 10) - assert.NoError(t, db.GetEngine(db.DefaultContext).Find(&ownedRepos, &repo_model.Repository{OwnerID: userID})) + assert.NoError(t, db.GetEngine(t.Context()).Find(&ownedRepos, &repo_model.Repository{OwnerID: userID})) if len(ownedRepos) > 0 { - err := DeleteUser(db.DefaultContext, user, false) + err := DeleteUser(t.Context(), user, false) assert.Error(t, err) assert.True(t, repo_model.IsErrUserOwnRepos(err)) return } orgUsers := make([]*organization.OrgUser, 0, 10) - assert.NoError(t, db.GetEngine(db.DefaultContext).Find(&orgUsers, &organization.OrgUser{UID: userID})) + assert.NoError(t, db.GetEngine(t.Context()).Find(&orgUsers, &organization.OrgUser{UID: userID})) for _, orgUser := range orgUsers { org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: orgUser.OrgID}) - if err := org_service.RemoveOrgUser(db.DefaultContext, org, user); err != nil { + if err := org_service.RemoveOrgUser(t.Context(), org, user); err != nil { assert.True(t, organization.IsErrLastOrgOwner(err)) return } } - assert.NoError(t, DeleteUser(db.DefaultContext, user, false)) + assert.NoError(t, DeleteUser(t.Context(), user, false)) unittest.AssertNotExistsBean(t, &user_model.User{ID: userID}) unittest.CheckConsistencyFor(t, &user_model.User{}, &repo_model.Repository{}) } @@ -59,7 +59,7 @@ func TestDeleteUser(t *testing.T) { test(11) org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) - assert.Error(t, DeleteUser(db.DefaultContext, org, false)) + assert.Error(t, DeleteUser(t.Context(), org, false)) } func TestPurgeUser(t *testing.T) { @@ -67,7 +67,7 @@ func TestPurgeUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}) - err := DeleteUser(db.DefaultContext, user, true) + err := DeleteUser(t.Context(), user, true) assert.NoError(t, err) unittest.AssertNotExistsBean(t, &user_model.User{ID: userID}) @@ -79,7 +79,7 @@ func TestPurgeUser(t *testing.T) { test(11) org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) - assert.Error(t, DeleteUser(db.DefaultContext, org, false)) + assert.Error(t, DeleteUser(t.Context(), org, false)) } func TestCreateUser(t *testing.T) { @@ -92,9 +92,9 @@ func TestCreateUser(t *testing.T) { MustChangePassword: false, } - assert.NoError(t, user_model.CreateUser(db.DefaultContext, user, &user_model.Meta{})) + assert.NoError(t, user_model.CreateUser(t.Context(), user, &user_model.Meta{})) - assert.NoError(t, DeleteUser(db.DefaultContext, user, false)) + assert.NoError(t, DeleteUser(t.Context(), user, false)) } func TestRenameUser(t *testing.T) { @@ -106,18 +106,18 @@ func TestRenameUser(t *testing.T) { Type: user_model.UserTypeIndividual, LoginType: auth.OAuth2, } - assert.ErrorIs(t, RenameUser(db.DefaultContext, u, "user_rename"), user_model.ErrUserIsNotLocal{}) + assert.ErrorIs(t, RenameUser(t.Context(), u, "user_rename"), user_model.ErrUserIsNotLocal{}) }) t.Run("Same username", func(t *testing.T) { - assert.NoError(t, RenameUser(db.DefaultContext, user, user.Name)) + assert.NoError(t, RenameUser(t.Context(), user, user.Name)) }) t.Run("Non usable username", func(t *testing.T) { usernames := []string{"--diff", ".well-known", "gitea-actions", "aaa.atom", "aa.png"} for _, username := range usernames { assert.Error(t, user_model.IsUsableUsername(username), "non-usable username: %s", username) - assert.Error(t, RenameUser(db.DefaultContext, user, username), "non-usable username: %s", username) + assert.Error(t, RenameUser(t.Context(), user, username), "non-usable username: %s", username) } }) @@ -126,7 +126,7 @@ func TestRenameUser(t *testing.T) { unittest.AssertNotExistsBean(t, &user_model.User{ID: user.ID, Name: caps}) unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: user.ID, OwnerName: user.Name}) - assert.NoError(t, RenameUser(db.DefaultContext, user, caps)) + assert.NoError(t, RenameUser(t.Context(), user, caps)) unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: user.ID, Name: caps}) unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: user.ID, OwnerName: caps}) @@ -135,20 +135,20 @@ func TestRenameUser(t *testing.T) { t.Run("Already exists", func(t *testing.T) { existUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - assert.ErrorIs(t, RenameUser(db.DefaultContext, user, existUser.Name), user_model.ErrUserAlreadyExist{Name: existUser.Name}) - assert.ErrorIs(t, RenameUser(db.DefaultContext, user, existUser.LowerName), user_model.ErrUserAlreadyExist{Name: existUser.LowerName}) + assert.ErrorIs(t, RenameUser(t.Context(), user, existUser.Name), user_model.ErrUserAlreadyExist{Name: existUser.Name}) + assert.ErrorIs(t, RenameUser(t.Context(), user, existUser.LowerName), user_model.ErrUserAlreadyExist{Name: existUser.LowerName}) newUsername := fmt.Sprintf("uSEr%d", existUser.ID) - assert.ErrorIs(t, RenameUser(db.DefaultContext, user, newUsername), user_model.ErrUserAlreadyExist{Name: newUsername}) + assert.ErrorIs(t, RenameUser(t.Context(), user, newUsername), user_model.ErrUserAlreadyExist{Name: newUsername}) }) t.Run("Normal", func(t *testing.T) { oldUsername := user.Name newUsername := "User_Rename" - assert.NoError(t, RenameUser(db.DefaultContext, user, newUsername)) + assert.NoError(t, RenameUser(t.Context(), user, newUsername)) unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: user.ID, Name: newUsername, LowerName: strings.ToLower(newUsername)}) - redirectUID, err := user_model.LookupUserRedirect(db.DefaultContext, oldUsername) + redirectUID, err := user_model.LookupUserRedirect(t.Context(), oldUsername) assert.NoError(t, err) assert.Equal(t, user.ID, redirectUID) @@ -175,24 +175,24 @@ func TestCreateUser_Issue5882(t *testing.T) { for _, v := range tt { setting.Admin.DisableRegularOrgCreation = v.disableOrgCreation - assert.NoError(t, user_model.CreateUser(db.DefaultContext, v.user, &user_model.Meta{})) + assert.NoError(t, user_model.CreateUser(t.Context(), v.user, &user_model.Meta{})) - u, err := user_model.GetUserByEmail(db.DefaultContext, v.user.Email) + u, err := user_model.GetUserByEmail(t.Context(), v.user.Email) assert.NoError(t, err) assert.Equal(t, !u.AllowCreateOrganization, v.disableOrgCreation) - assert.NoError(t, DeleteUser(db.DefaultContext, v.user, false)) + assert.NoError(t, DeleteUser(t.Context(), v.user, false)) } } func TestDeleteInactiveUsers(t *testing.T) { addUser := func(name, email string, createdUnix timeutil.TimeStamp, active bool) { inactiveUser := &user_model.User{Name: name, LowerName: strings.ToLower(name), Email: email, CreatedUnix: createdUnix, IsActive: active} - _, err := db.GetEngine(db.DefaultContext).NoAutoTime().Insert(inactiveUser) + _, err := db.GetEngine(t.Context()).NoAutoTime().Insert(inactiveUser) assert.NoError(t, err) inactiveUserEmail := &user_model.EmailAddress{UID: inactiveUser.ID, IsPrimary: true, Email: email, LowerEmail: strings.ToLower(email), IsActivated: active} - err = db.Insert(db.DefaultContext, inactiveUserEmail) + err = db.Insert(t.Context(), inactiveUserEmail) assert.NoError(t, err) } addUser("user-inactive-10", "user-inactive-10@test.com", timeutil.TimeStampNow().Add(-600), false) @@ -201,7 +201,7 @@ func TestDeleteInactiveUsers(t *testing.T) { addUser("user-active-5", "user-active-5@test.com", timeutil.TimeStampNow().Add(-300), true) unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user-inactive-10"}) unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user-inactive-10@test.com"}) - assert.NoError(t, DeleteInactiveUsers(db.DefaultContext, 8*time.Minute)) + assert.NoError(t, DeleteInactiveUsers(t.Context(), 8*time.Minute)) unittest.AssertNotExistsBean(t, &user_model.User{Name: "user-inactive-10"}) unittest.AssertNotExistsBean(t, &user_model.EmailAddress{Email: "user-inactive-10@test.com"}) unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user-inactive-5"}) diff --git a/services/versioned_migration/migration.go b/services/versioned_migration/migration.go index b66d8535310..c064bf79137 100644 --- a/services/versioned_migration/migration.go +++ b/services/versioned_migration/migration.go @@ -20,5 +20,5 @@ func Migrate(ctx context.Context, x *xorm.Engine) error { } defer release() - return migrations.Migrate(x) + return migrations.Migrate(ctx, x) } diff --git a/services/webhook/deliver_test.go b/services/webhook/deliver_test.go index 1d32d7b7725..efbef1fc894 100644 --- a/services/webhook/deliver_test.go +++ b/services/webhook/deliver_test.go @@ -12,7 +12,6 @@ import ( "testing" "time" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/hostmatcher" @@ -105,7 +104,7 @@ func TestWebhookDeliverAuthorizationHeader(t *testing.T) { } err := hook.SetHeaderAuthorization("Bearer s3cr3t-t0ken") assert.NoError(t, err) - assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook)) + assert.NoError(t, webhook_model.CreateWebhook(t.Context(), hook)) hookTask := &webhook_model.HookTask{ HookID: hook.ID, @@ -113,7 +112,7 @@ func TestWebhookDeliverAuthorizationHeader(t *testing.T) { PayloadVersion: 2, } - hookTask, err = webhook_model.CreateHookTask(db.DefaultContext, hookTask) + hookTask, err = webhook_model.CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) assert.NotNil(t, hookTask) @@ -170,7 +169,7 @@ func TestWebhookDeliverHookTask(t *testing.T) { ContentType: webhook_model.ContentTypeJSON, Meta: `{"message_type":0}`, // text } - assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook)) + assert.NoError(t, webhook_model.CreateWebhook(t.Context(), hook)) t.Run("Version 1", func(t *testing.T) { hookTask := &webhook_model.HookTask{ @@ -180,7 +179,7 @@ func TestWebhookDeliverHookTask(t *testing.T) { PayloadVersion: 1, } - hookTask, err := webhook_model.CreateHookTask(db.DefaultContext, hookTask) + hookTask, err := webhook_model.CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) assert.NotNil(t, hookTask) @@ -206,7 +205,7 @@ func TestWebhookDeliverHookTask(t *testing.T) { PayloadVersion: 2, } - hookTask, err = webhook_model.CreateHookTask(db.DefaultContext, hookTask) + hookTask, err = webhook_model.CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) assert.NotNil(t, hookTask) @@ -266,7 +265,7 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) { URL: s.URL + "/" + typ, Meta: "{}", } - assert.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook)) + assert.NoError(t, webhook_model.CreateWebhook(t.Context(), hook)) hookTask := &webhook_model.HookTask{ HookID: hook.ID, @@ -275,7 +274,7 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) { PayloadVersion: 2, } - hookTask, err := webhook_model.CreateHookTask(db.DefaultContext, hookTask) + hookTask, err := webhook_model.CreateHookTask(t.Context(), hookTask) assert.NoError(t, err) assert.NotNil(t, hookTask) diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go index 672abd5c95d..80de6b00fdb 100644 --- a/services/webhook/notifier.go +++ b/services/webhook/notifier.go @@ -481,6 +481,7 @@ func (m *webhookNotifier) DeleteComment(ctx context.Context, doer *user_model.Us log.Error("LoadPoster: %v", err) return } + comment.Issue = nil // reload issue to ensure it has the latest data, especially the number of comments if err = comment.LoadIssue(ctx); err != nil { log.Error("LoadIssue: %v", err) return diff --git a/services/webhook/webhook_test.go b/services/webhook/webhook_test.go index 5a805347e38..34bcfd3df9d 100644 --- a/services/webhook/webhook_test.go +++ b/services/webhook/webhook_test.go @@ -6,7 +6,6 @@ package webhook import ( "testing" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -43,7 +42,7 @@ func TestPrepareWebhooks(t *testing.T) { for _, hookTask := range hookTasks { unittest.AssertNotExistsBean(t, hookTask) } - assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}})) + assert.NoError(t, PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}})) for _, hookTask := range hookTasks { unittest.AssertExistsAndLoadBean(t, hookTask) } @@ -60,7 +59,7 @@ func TestPrepareWebhooksBranchFilterMatch(t *testing.T) { unittest.AssertNotExistsBean(t, hookTask) } // this test also ensures that * doesn't handle / in any special way (like shell would) - assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}})) + assert.NoError(t, PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}})) for _, hookTask := range hookTasks { unittest.AssertExistsAndLoadBean(t, hookTask) } @@ -76,7 +75,7 @@ func TestPrepareWebhooksBranchFilterNoMatch(t *testing.T) { for _, hookTask := range hookTasks { unittest.AssertNotExistsBean(t, hookTask) } - assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"})) + assert.NoError(t, PrepareWebhooks(t.Context(), EventSource{Repository: repo}, webhook_module.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"})) for _, hookTask := range hookTasks { unittest.AssertNotExistsBean(t, hookTask) @@ -88,6 +87,6 @@ func TestWebhookUserMail(t *testing.T) { defer test.MockVariableValue(&setting.Service.NoReplyAddress, "no-reply.com")() user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) - assert.Equal(t, user.GetPlaceholderEmail(), convert.ToUser(db.DefaultContext, user, nil).Email) - assert.Equal(t, user.Email, convert.ToUser(db.DefaultContext, user, user).Email) + assert.Equal(t, user.GetPlaceholderEmail(), convert.ToUser(t.Context(), user, nil).Email) + assert.Equal(t, user.Email, convert.ToUser(t.Context(), user, user).Email) } diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go index 6ea3ca9c1b7..a54f2c96d5e 100644 --- a/services/wiki/wiki_test.go +++ b/services/wiki/wiki_test.go @@ -144,11 +144,11 @@ func TestRepository_InitWiki(t *testing.T) { unittest.PrepareTestEnv(t) // repo1 already has a wiki repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - assert.NoError(t, InitWiki(git.DefaultContext, repo1)) + assert.NoError(t, InitWiki(t.Context(), repo1)) // repo2 does not already have a wiki repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) - assert.NoError(t, InitWiki(git.DefaultContext, repo2)) + assert.NoError(t, InitWiki(t.Context(), repo2)) assert.True(t, repo2.HasWiki()) } @@ -164,9 +164,9 @@ func TestRepository_AddWikiPage(t *testing.T) { } { t.Run("test wiki exist: "+userTitle, func(t *testing.T) { webPath := UserTitleToWebPath("", userTitle) - assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg)) + assert.NoError(t, AddWikiPage(t.Context(), doer, repo, webPath, wikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo()) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo()) require.NoError(t, err) defer gitRepo.Close() @@ -182,7 +182,7 @@ func TestRepository_AddWikiPage(t *testing.T) { t.Run("check wiki already exist", func(t *testing.T) { t.Parallel() // test for already-existing wiki name - err := AddWikiPage(git.DefaultContext, doer, repo, "Home", wikiContent, commitMsg) + err := AddWikiPage(t.Context(), doer, repo, "Home", wikiContent, commitMsg) assert.Error(t, err) assert.True(t, repo_model.IsErrWikiAlreadyExist(err)) }) @@ -190,7 +190,7 @@ func TestRepository_AddWikiPage(t *testing.T) { t.Run("check wiki reserved name", func(t *testing.T) { t.Parallel() // test for reserved wiki name - err := AddWikiPage(git.DefaultContext, doer, repo, "_edit", wikiContent, commitMsg) + err := AddWikiPage(t.Context(), doer, repo, "_edit", wikiContent, commitMsg) assert.Error(t, err) assert.True(t, repo_model.IsErrWikiReservedName(err)) }) @@ -210,10 +210,10 @@ func TestRepository_EditWikiPage(t *testing.T) { } { webPath := UserTitleToWebPath("", newWikiName) unittest.PrepareTestEnv(t) - assert.NoError(t, EditWikiPage(git.DefaultContext, doer, repo, "Home", webPath, newWikiContent, commitMsg)) + assert.NoError(t, EditWikiPage(t.Context(), doer, repo, "Home", webPath, newWikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo()) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo()) assert.NoError(t, err) masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch) assert.NoError(t, err) @@ -234,10 +234,10 @@ func TestRepository_DeleteWikiPage(t *testing.T) { unittest.PrepareTestEnv(t) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home")) + assert.NoError(t, DeleteWikiPage(t.Context(), doer, repo, "Home")) // Now need to show that the page has been added: - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo()) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo()) require.NoError(t, err) defer gitRepo.Close() @@ -251,7 +251,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) { func TestPrepareWikiFileName(t *testing.T) { unittest.PrepareTestEnv(t) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo()) + gitRepo, err := gitrepo.OpenRepository(t.Context(), repo.WikiStorageRepo()) require.NoError(t, err) defer gitRepo.Close() @@ -301,10 +301,10 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) { // Now create a temporaryDirectory tmpDir := t.TempDir() - err := git.InitRepository(git.DefaultContext, tmpDir, true, git.Sha1ObjectFormat.Name()) + err := git.InitRepository(t.Context(), tmpDir, true, git.Sha1ObjectFormat.Name()) assert.NoError(t, err) - gitRepo, err := git.OpenRepository(git.DefaultContext, tmpDir) + gitRepo, err := git.OpenRepository(t.Context(), tmpDir) require.NoError(t, err) defer gitRepo.Close() diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 596f703131e..46900f7b85e 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -44,7 +44,7 @@ parts: source: . stage-packages: [ git, sqlite3, openssh-client ] build-packages: [ git, libpam0g-dev, libsqlite3-dev, build-essential] - build-snaps: [ go/1.24/stable, node/22/stable ] + build-snaps: [ go/1.25/stable, node/22/stable ] build-environment: - LDFLAGS: "" override-pull: | diff --git a/stylelint.config.js b/stylelint.config.js index c57c1fd3a33..bd11307b531 100644 --- a/stylelint.config.js +++ b/stylelint.config.js @@ -10,6 +10,9 @@ const cssVarFiles = [ export default defineConfig({ extends: 'stylelint-config-recommended', + reportUnscopedDisables: true, + reportNeedlessDisables: true, + reportInvalidScopeDisables: true, plugins: [ 'stylelint-declaration-strict-value', 'stylelint-declaration-block-no-ignored-properties', diff --git a/templates/admin/config_settings.tmpl b/templates/admin/config_settings.tmpl index 6b9bb8275cc..9bd37afa7d5 100644 --- a/templates/admin/config_settings.tmpl +++ b/templates/admin/config_settings.tmpl @@ -24,7 +24,7 @@ {{ctx.Locale.Tr "repository"}}
-
+
{{ctx.Locale.Tr "admin.config.open_with_editor_app_help"}} @@ -32,7 +32,16 @@
- + {{$cfg := .SystemConfig.Repository.OpenWithEditorApps}} + + +
+ +
+ + {{$cfg = .SystemConfig.Repository.GitGuideRemoteName}} + +
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index e9526818e33..62bc625bda6 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -18,9 +18,9 @@ {{end}} - {{template "base/head_script" .}} {{template "base/head_opengraph" .}} {{template "base/head_style" .}} + {{template "base/head_script" .}} {{template "custom/header" .}} diff --git a/templates/base/head_opengraph.tmpl b/templates/base/head_opengraph.tmpl index f1f38999d2e..cb96fb6d6de 100644 --- a/templates/base/head_opengraph.tmpl +++ b/templates/base/head_opengraph.tmpl @@ -3,14 +3,14 @@ - + {{if .ContextUser.Description}} {{end}} {{else if .Repository}} {{if .Issue}} - + {{if .Issue.Content}} {{end}} @@ -26,7 +26,7 @@ {{end}} {{else}} - + {{if .Repository.Description}} {{end}} diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl index d94bb4c62b2..f2d4ee0b28e 100644 --- a/templates/org/settings/options.tmpl +++ b/templates/org/settings/options.tmpl @@ -29,29 +29,6 @@
-
-
- -
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
diff --git a/templates/org/settings/options_dangerzone.tmpl b/templates/org/settings/options_dangerzone.tmpl index 01cf3fd4051..d01252e3e1b 100644 --- a/templates/org/settings/options_dangerzone.tmpl +++ b/templates/org/settings/options_dangerzone.tmpl @@ -3,6 +3,16 @@
+
+
+
{{ctx.Locale.Tr "org.settings.visibility"}}
+
{{ctx.Locale.Tr "org.settings.visibility_desc"}}
+
+
+ +
+
+
{{ctx.Locale.Tr "org.settings.rename"}}
@@ -25,15 +35,55 @@
+ +