diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml index d3eac5357a..c127dd2eba 100644 --- a/.forgejo/workflows/renovate.yml +++ b/.forgejo/workflows/renovate.yml @@ -28,7 +28,7 @@ jobs: runs-on: docker container: - image: data.forgejo.org/renovate/renovate:41.23.2 + image: data.forgejo.org/renovate/renovate:41.32.1 steps: - name: Load renovate repo cache diff --git a/.golangci.yml b/.golangci.yml index 6679a1850e..17d39c1456 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -42,6 +42,8 @@ linters: desc: do not use the ini package, use gitea's config system instead - pkg: github.com/minio/sha256-simd desc: use crypto/sha256 instead, see https://codeberg.org/forgejo/forgejo/pulls/1528 + - pkg: github.com/go-git/go-git + desc: use forgejo.org/modules/git instead, see https://codeberg.org/forgejo/forgejo/pulls/4941 gocritic: disabled-checks: - ifElseChain diff --git a/Makefile b/Makefile index c09e0180eb..1db44e6f26 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasour GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.34.0 # renovate: datasource=go GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.5.2 # renovate: datasource=go -RENOVATE_NPM_PACKAGE ?= renovate@41.23.2 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate +RENOVATE_NPM_PACKAGE ?= renovate@41.32.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate # https://github.com/disposable-email-domains/disposable-email-domains/commits/main/ DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ... diff --git a/go.mod b/go.mod index 139095099b..1421f503fe 100644 --- a/go.mod +++ b/go.mod @@ -45,15 +45,14 @@ require ( github.com/go-chi/cors v1.2.2 github.com/go-co-op/gocron v1.37.0 github.com/go-enry/go-enry/v2 v2.9.2 - github.com/go-git/go-git/v5 v5.13.2 github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-openapi/spec v0.21.0 github.com/go-sql-driver/mysql v1.9.3 - github.com/go-webauthn/webauthn v0.13.1 + github.com/go-webauthn/webauthn v0.13.3 github.com/gobwas/glob v0.2.3 github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 - github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/golang-jwt/jwt/v5 v5.2.3 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/google/go-github/v64 v64.0.0 github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 @@ -166,11 +165,12 @@ require ( github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect + github.com/go-git/go-git/v5 v5.13.2 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-openapi/jsonpointer v0.21.1 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.1 // indirect - github.com/go-webauthn/x v0.1.22 // indirect + github.com/go-webauthn/x v0.1.23 // indirect github.com/goccy/go-json v0.10.5 // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect diff --git a/go.sum b/go.sum index 3c906b45c6..cf10843262 100644 --- a/go.sum +++ b/go.sum @@ -250,10 +250,10 @@ github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI6 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/go-webauthn/webauthn v0.13.1 h1:Q3/GLXsckVJUPE+BGR6ex26yRIiZ/X2ITaMeSkOftuc= -github.com/go-webauthn/webauthn v0.13.1/go.mod h1:HeaBromTjgMg1sHZOzyjEiqcrk4Og7mxafDTWDepaXI= -github.com/go-webauthn/x v0.1.22 h1:rHilV/rYXawarI0uA3uZ5nhLb30Ex8RgbVAsOSt/57o= -github.com/go-webauthn/x v0.1.22/go.mod h1:+iV9BF4OsvLYzETdc0lmQO2webTos10oH6QydSoWxDM= +github.com/go-webauthn/webauthn v0.13.3 h1:rvX539Gy9U4xAuFQRFJtkgoH5E1GEUyIVbHUDC89Mo4= +github.com/go-webauthn/webauthn v0.13.3/go.mod h1:H9EdVnxXFMMJyx8Nd/OL3aFFEop3Rb+Af1naR0IbuUQ= +github.com/go-webauthn/x v0.1.23 h1:9lEO0s+g8iTyz5Vszlg/rXTGrx3CjcD0RZQ1GPZCaxI= +github.com/go-webauthn/x v0.1.23/go.mod h1:AJd3hI7NfEp/4fI6T4CHD753u91l510lglU7/NMN6+E= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= @@ -268,8 +268,8 @@ github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= +github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= diff --git a/models/fixtures/TestAddTeamReviewRequest/issue.yml b/models/fixtures/TestAddTeamReviewRequest/issue.yml new file mode 100644 index 0000000000..a1bcf2921f --- /dev/null +++ b/models/fixtures/TestAddTeamReviewRequest/issue.yml @@ -0,0 +1,16 @@ +- + id: 23 + repo_id: 2 + index: 3 + poster_id: 2 + original_author_id: 0 + name: protected branch pull + content: pull request to a protected branch + milestone_id: 0 + priority: 0 + is_pull: true + is_closed: false + num_comments: 0 + created_unix: 1707270422 + updated_unix: 1707270422 + is_locked: false \ No newline at end of file diff --git a/models/fixtures/TestAddTeamReviewRequest/protected_branch.yml b/models/fixtures/TestAddTeamReviewRequest/protected_branch.yml new file mode 100644 index 0000000000..93909bd991 --- /dev/null +++ b/models/fixtures/TestAddTeamReviewRequest/protected_branch.yml @@ -0,0 +1,28 @@ +- id: 1 + repo_id: 2 + branch_name: protected-main + can_push: false + enable_whitelist: true + whitelist_user_i_ds: [1] + whitelist_team_i_ds: [] + enable_merge_whitelist: true + whitelist_deploy_keys: false + merge_whitelist_user_i_ds: [1] + merge_whitelist_team_i_ds: [] + enable_status_check: false + status_check_contexts: [] + enable_approvals_whitelist: true + approvals_whitelist_user_i_ds: [] + approvals_whitelist_team_i_ds: [1] + required_approvals: 1 + block_on_rejected_reviews: true + block_on_official_review_requests: true + block_on_outdated_branch: true + dismiss_stale_approvals: true + ignore_stale_approvals: false + require_signed_commits: false + protected_file_patterns: "" + unprotected_file_patterns: "" + apply_to_admins: true + created_unix: 1752513073 + updated_unix: 1752513073 \ No newline at end of file diff --git a/models/fixtures/TestAddTeamReviewRequest/pull_request.yml b/models/fixtures/TestAddTeamReviewRequest/pull_request.yml new file mode 100644 index 0000000000..067bb01324 --- /dev/null +++ b/models/fixtures/TestAddTeamReviewRequest/pull_request.yml @@ -0,0 +1,12 @@ +- + id: 11 + type: 0 # gitea pull request + status: 2 # mergeable + issue_id: 23 + index: 3 + head_repo_id: 2 + base_repo_id: 2 + head_branch: feature/protected-branch-pr + base_branch: protected-main + merge_base: 4a357436d925b5c974181ff12a994538ddc5a269 + has_merged: false \ No newline at end of file diff --git a/models/issues/review.go b/models/issues/review.go index 584704d3e8..5370117a81 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -781,10 +781,6 @@ func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organizat official, err := IsOfficialReviewerTeam(ctx, issue, reviewer) if err != nil { return nil, fmt.Errorf("isOfficialReviewerTeam(): %w", err) - } else if !official { - if official, err = IsOfficialReviewer(ctx, issue, doer); err != nil { - return nil, fmt.Errorf("isOfficialReviewer(): %w", err) - } } if review, err = CreateReview(ctx, CreateReviewOptions{ @@ -797,12 +793,6 @@ func AddTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organizat return nil, err } - if official { - if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_team_id=?", false, issue.ID, reviewer.ID); err != nil { - return nil, err - } - } - comment, err := CreateComment(ctx, &CreateCommentOptions{ Type: CommentTypeReviewRequest, Doer: doer, diff --git a/models/issues/review_test.go b/models/issues/review_test.go index 33d131c225..6e2f6ddfa8 100644 --- a/models/issues/review_test.go +++ b/models/issues/review_test.go @@ -8,6 +8,7 @@ import ( "forgejo.org/models/db" issues_model "forgejo.org/models/issues" + organization_model "forgejo.org/models/organization" repo_model "forgejo.org/models/repo" "forgejo.org/models/unittest" user_model "forgejo.org/models/user" @@ -319,3 +320,80 @@ func TestAddReviewRequest(t *testing.T) { require.Error(t, err) assert.True(t, issues_model.IsErrReviewRequestOnClosedPR(err)) } + +func TestAddTeamReviewRequest(t *testing.T) { + defer unittest.OverrideFixtures("models/fixtures/TestAddTeamReviewRequest")() + require.NoError(t, unittest.PrepareTestDatabase()) + + setupForProtectedBranch := func() (*issues_model.Issue, *user_model.User) { + // From override models/fixtures/TestAddTeamReviewRequest/issue.yml; issue #23 is a PR into a protected branch + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 23}) + require.NoError(t, issue.LoadRepo(db.DefaultContext)) + doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) + return issue, doer + } + + t.Run("Protected branch, not official team", func(t *testing.T) { + issue, doer := setupForProtectedBranch() + // Team 2 is not part of the whitelist for this protected branch + team := unittest.AssertExistsAndLoadBean(t, &organization_model.Team{ID: 2}) + + comment, err := issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer) + require.NoError(t, err) + require.NotNil(t, comment) + + review, err := issues_model.GetTeamReviewerByIssueIDAndTeamID(db.DefaultContext, issue.ID, team.ID) + require.NoError(t, err) + require.NotNil(t, review) + assert.Equal(t, issues_model.ReviewTypeRequest, review.Type) + assert.Equal(t, team.ID, review.ReviewerTeamID) + // This review request should not be marked official because it is not a request for a team in the branch + // protection rule's whitelist... + assert.False(t, review.Official) + }) + + t.Run("Protected branch, official team", func(t *testing.T) { + issue, doer := setupForProtectedBranch() + // Team 1 is part of the whitelist for this protected branch + team := unittest.AssertExistsAndLoadBean(t, &organization_model.Team{ID: 1}) + + comment, err := issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer) + require.NoError(t, err) + require.NotNil(t, comment) + + review, err := issues_model.GetTeamReviewerByIssueIDAndTeamID(db.DefaultContext, issue.ID, team.ID) + require.NoError(t, err) + require.NotNil(t, review) + assert.Equal(t, issues_model.ReviewTypeRequest, review.Type) + assert.Equal(t, team.ID, review.ReviewerTeamID) + // Expected to be considered official because team 1 is in the review whitelist for this protected branch + assert.True(t, review.Official) + }) + + t.Run("Unprotected branch, official team", func(t *testing.T) { + // Working on a PR into a branch that is not protected, issue #2 + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) + require.NoError(t, issue.LoadRepo(db.DefaultContext)) + doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + // team is a team that has write perms against the repo + team := unittest.AssertExistsAndLoadBean(t, &organization_model.Team{ID: 1}) + + comment, err := issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer) + require.NoError(t, err) + require.NotNil(t, comment) + + review, err := issues_model.GetTeamReviewerByIssueIDAndTeamID(db.DefaultContext, issue.ID, team.ID) + require.NoError(t, err) + require.NotNil(t, review) + assert.Equal(t, issues_model.ReviewTypeRequest, review.Type) + assert.Equal(t, team.ID, review.ReviewerTeamID) + // Will not be marked as official because PR #2 there's no branch protection rule that enables whitelist + // approvals (verifying logic in `IsOfficialReviewerTeam` indirectly) + assert.False(t, review.Official) + + // Adding the same team review request again should be a noop + comment, err = issues_model.AddTeamReviewRequest(db.DefaultContext, issue, team, doer) + require.NoError(t, err) + require.Nil(t, comment) + }) +} diff --git a/models/repo/git.go b/models/repo/git.go index 692176c8f6..11f6452be5 100644 --- a/models/repo/git.go +++ b/models/repo/git.go @@ -29,6 +29,8 @@ const ( MergeStyleRebaseUpdate MergeStyle = "rebase-update-only" ) +var MergeStyles = []MergeStyle{MergeStyleMerge, MergeStyleRebase, MergeStyleRebaseMerge, MergeStyleSquash, MergeStyleFastForwardOnly, MergeStyleManuallyMerged, MergeStyleRebaseUpdate} + type UpdateStyle string const ( diff --git a/modules/base/tool.go b/modules/base/tool.go index fd6a7c2b77..e3a3ff4a23 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -114,7 +114,7 @@ func EntryIcon(entry *git.TreeEntry) string { return "file-symlink-file" case entry.IsDir(): return "file-directory-fill" - case entry.IsSubModule(): + case entry.IsSubmodule(): return "file-submodule" } diff --git a/modules/git/commit.go b/modules/git/commit.go index 1228b4523b..4fb13ecd4f 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -16,8 +16,6 @@ import ( "forgejo.org/modules/log" "forgejo.org/modules/util" - - "github.com/go-git/go-git/v5/config" ) // Commit represents a git commit. @@ -29,8 +27,8 @@ type Commit struct { CommitMessage string Signature *ObjectSignature - Parents []ObjectID // ID strings - submoduleCache *ObjectCache + Parents []ObjectID // ID strings + submodules map[string]Submodule // submodule indexed by path } // Message returns the commit message. Same as retrieving CommitMessage directly. @@ -352,64 +350,6 @@ func (c *Commit) GetFileContent(filename string, limit int) (string, error) { return string(bytes), nil } -// GetSubModules get all the sub modules of current revision git tree -func (c *Commit) GetSubModules() (*ObjectCache, error) { - if c.submoduleCache != nil { - return c.submoduleCache, nil - } - - entry, err := c.GetTreeEntryByPath(".gitmodules") - if err != nil { - if _, ok := err.(ErrNotExist); ok { - return nil, nil - } - return nil, err - } - - content, err := entry.Blob().GetBlobContent(10 * 1024) - if err != nil { - return nil, err - } - - c.submoduleCache, err = parseSubmoduleContent([]byte(content)) - if err != nil { - return nil, err - } - return c.submoduleCache, nil -} - -func parseSubmoduleContent(bs []byte) (*ObjectCache, error) { - cfg := config.NewModules() - if err := cfg.Unmarshal(bs); err != nil { - return nil, err - } - submoduleCache := newObjectCache() - if len(cfg.Submodules) == 0 { - return nil, errors.New("no submodules found") - } - for _, subModule := range cfg.Submodules { - submoduleCache.Set(subModule.Path, subModule.URL) - } - - return submoduleCache, nil -} - -// GetSubModule returns the URL to the submodule according entryname -func (c *Commit) GetSubModule(entryname string) (string, error) { - modules, err := c.GetSubModules() - if err != nil { - return "", err - } - - if modules != nil { - module, has := modules.Get(entryname) - if has { - return module.(string), nil - } - } - return "", nil -} - // GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only') func (c *Commit) GetBranchName() (string, error) { cmd := NewCommand(c.repo.Ctx, "name-rev", "--exclude", "refs/tags/*", "--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) diff --git a/modules/git/commit_info.go b/modules/git/commit_info.go index 8d9142d362..6511a1689a 100644 --- a/modules/git/commit_info.go +++ b/modules/git/commit_info.go @@ -15,9 +15,9 @@ import ( // CommitInfo describes the first commit with the provided entry type CommitInfo struct { - Entry *TreeEntry - Commit *Commit - SubModuleFile *SubModuleFile + Entry *TreeEntry + Commit *Commit + Submodule Submodule } // GetCommitsInfo gets information of all commits that are corresponding to these entries @@ -71,19 +71,18 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath } // If the entry if a submodule add a submodule file for this - if entry.IsSubModule() { + if entry.IsSubmodule() { var fullPath string if len(treePath) > 0 { fullPath = treePath + "/" + entry.Name() } else { fullPath = entry.Name() } - subModuleURL, err := commit.GetSubModule(fullPath) + submodule, err := commit.GetSubmodule(fullPath, entry) if err != nil { return nil, nil, err } - subModuleFile := NewSubModuleFile(commitsInfo[i].Commit, subModuleURL, entry.ID.String()) - commitsInfo[i].SubModuleFile = subModuleFile + commitsInfo[i].Submodule = submodule } } diff --git a/modules/git/commit_test.go b/modules/git/commit_test.go index 484827149c..ee57a735e6 100644 --- a/modules/git/commit_test.go +++ b/modules/git/commit_test.go @@ -436,33 +436,3 @@ func TestGetAllBranches(t *testing.T) { assert.Equal(t, []string{"branch1", "branch2", "master"}, branches) } - -func Test_parseSubmoduleContent(t *testing.T) { - submoduleFiles := []struct { - fileContent string - expectedPath string - expectedURL string - }{ - { - fileContent: `[submodule "jakarta-servlet"] -url = ../../ALP-pool/jakarta-servlet -path = jakarta-servlet`, - expectedPath: "jakarta-servlet", - expectedURL: "../../ALP-pool/jakarta-servlet", - }, - { - fileContent: `[submodule "jakarta-servlet"] -path = jakarta-servlet -url = ../../ALP-pool/jakarta-servlet`, - expectedPath: "jakarta-servlet", - expectedURL: "../../ALP-pool/jakarta-servlet", - }, - } - for _, kase := range submoduleFiles { - submodule, err := parseSubmoduleContent([]byte(kase.fileContent)) - require.NoError(t, err) - v, ok := submodule.Get(kase.expectedPath) - assert.True(t, ok) - assert.Equal(t, kase.expectedURL, v) - } -} diff --git a/modules/git/diff_compare.go b/modules/git/diff_compare.go new file mode 100644 index 0000000000..0eba8cb541 --- /dev/null +++ b/modules/git/diff_compare.go @@ -0,0 +1,56 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later +package git + +import ( + "bytes" + "context" + "fmt" + "os" + + "forgejo.org/modules/log" + "forgejo.org/modules/util" +) + +// CheckIfDiffDiffers returns if the diff of the newCommitID and +// oldCommitID with the merge base of the base branch has changed. +// +// Informally it checks if the following two diffs are exactly the same in their +// contents, thus ignoring different commit IDs, headers and messages: +// 1. git diff --merge-base baseReference newCommitID +// 2. git diff --merge-base baseReference oldCommitID +func (repo *Repository) CheckIfDiffDiffers(base, oldCommitID, newCommitID string, env []string) (hasChanged bool, err error) { + cmd := NewCommand(repo.Ctx, "diff", "--name-only", "-z").AddDynamicArguments(newCommitID, oldCommitID, base) + stdoutReader, stdoutWriter, err := os.Pipe() + if err != nil { + return false, fmt.Errorf("unable to open pipe for to run diff: %w", err) + } + + stderr := new(bytes.Buffer) + if err := cmd.Run(&RunOpts{ + Dir: repo.Path, + Stdout: stdoutWriter, + Stderr: stderr, + PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { + _ = stdoutWriter.Close() + defer func() { + _ = stdoutReader.Close() + }() + return util.IsEmptyReader(stdoutReader) + }, + }); err != nil { + if err == util.ErrNotEmpty { + return true, nil + } + err = ConcatenateError(err, stderr.String()) + + log.Error("Unable to run git diff on %s %s %s in %q: Error: %v", + newCommitID, oldCommitID, base, + repo.Path, + err) + + return false, fmt.Errorf("Unable to run git diff --name-only -z %s %s %s: %w", newCommitID, oldCommitID, base, err) + } + + return false, nil +} diff --git a/modules/git/diff_compare_test.go b/modules/git/diff_compare_test.go new file mode 100644 index 0000000000..433497b5c4 --- /dev/null +++ b/modules/git/diff_compare_test.go @@ -0,0 +1,421 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: GPL-3.0-or-later +package git + +import ( + "bytes" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCheckIfDiffDiffers(t *testing.T) { + tmpDir := t.TempDir() + + err := InitRepository(t.Context(), tmpDir, false, Sha1ObjectFormat.Name()) + require.NoError(t, err) + + gitRepo, err := openRepositoryWithDefaultContext(tmpDir) + require.NoError(t, err) + defer gitRepo.Close() + + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "main").Run(&RunOpts{Dir: tmpDir})) + + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("aaa"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "initial commit").Run(&RunOpts{Dir: tmpDir})) + + t.Run("Simple fast-forward", func(t *testing.T) { + // Check that A--B--C, where A is the base branch. + + t.Run("Different diff", func(t *testing.T) { + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "a-1", "main").Run(&RunOpts{Dir: tmpDir})) + + // B commit + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "a-2").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("ccc"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "a-1", "a-2", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + + t.Run("Same diff", func(t *testing.T) { + // Because C is a empty commit, the diff does not differ relative to the + // base branch. + + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "a-3", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "a-4").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "--allow-empty", "-m", "No changes to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "a-3", "a-4", nil) + require.NoError(t, err) + assert.False(t, changed) + }) + }) + + t.Run("Merge-base is base reference", func(t *testing.T) { + // B + // / + // A + // \ + // C + t.Run("Different diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "b-1", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changed to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "b-2", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("ccc"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changed to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "b-1", "b-2", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + + t.Run("Same diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "b-3", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changed to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "b-4", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changed to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "b-3", "b-4", nil) + require.NoError(t, err) + assert.False(t, changed) + }) + }) + + t.Run("Merge-base is different", func(t *testing.T) { + // B + // / + // A--D + // \ + // C + // Where D is the base reference. + + // D commit, where A is `main`. + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "main-D", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "FUNFACT"), []byte("Smithy was the runner up to be Forgejo's name"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "FUNFACT").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Forgejo history").Run(&RunOpts{Dir: tmpDir})) + + t.Run("Different diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "c-1", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "c-2", "main-D").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "FUNFACT"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "FUNFACT").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the funfact").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main-D", "c-1", "c-2", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + + t.Run("Same diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "c-3", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "c-4", "main-D").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main-D", "c-3", "c-4", nil) + require.NoError(t, err) + assert.False(t, changed) + }) + }) + + t.Run("Merge commit", func(t *testing.T) { + // B + // / + // A - D + // \ + // C + // + // From B, it merges D where E is the merge commit : + // B---E + // / / + // A---D + // \ + // C + + t.Run("Different diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "d-1", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + // E commit + require.NoError(t, NewCommand(t.Context(), "merge", "--no-ff", "main-D").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "d-2", "main-D").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "FUNFACT"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "FUNFACT").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the funfact").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main-D", "d-1", "d-2", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + + t.Run("Same diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "d-3", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + // Merges D. + require.NoError(t, NewCommand(t.Context(), "merge", "--no-ff", "main-D").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "d-4", "main-D").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main-D", "d-3", "d-4", nil) + require.NoError(t, err) + assert.False(t, changed) + }) + }) + + t.Run("Non-typical rebase", func(t *testing.T) { + // B + // / + // A--D + // \ + // C + // Where D is the base reference. + // B was rebased onto D, which produced C. + // B and D made the same change to same file. + + // D commit. + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "main-D-2", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "FUNFACT"), []byte("Smithy was the runner up to be Forgejo's name"), 0o600)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("ccc"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "FUNFACT", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Forgejo history").Run(&RunOpts{Dir: tmpDir})) + + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "e-1", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "CONTACT"), []byte("@example.com"), 0o600)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("ccc"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README", "CONTACT").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the contact and README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "e-2").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "rebase", "main-D-2").Run(&RunOpts{Dir: tmpDir})) + + // The diff changed, because it no longers shows the change made to `README`. + changed, err := gitRepo.CheckIfDiffDiffers("main-D-2", "e-1", "e-2", nil) + require.NoError(t, err) + assert.False(t, changed) // This should be true. + }) + + t.Run("Directory", func(t *testing.T) { + // B + // / + // A + // \ + // C + t.Run("Same directory", func(t *testing.T) { + t.Run("Different diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-1", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "docs"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docs", "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "docs/README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changed to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-2", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "docs"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docs", "README"), []byte("ccc"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "docs/README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changed to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "f-1", "f-2", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + + t.Run("Same diff", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-3", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "docs"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docs", "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "docs/README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changed to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-4", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "docs"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docs", "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "docs/README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "f-3", "f-4", nil) + require.NoError(t, err) + assert.False(t, changed) + }) + }) + + t.Run("Different directory", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-5", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "docs"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docs", "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "docs/README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-6", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "documentation"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "documentation", "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "documentation/README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "f-5", "f-6", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + + t.Run("Directory and file", func(t *testing.T) { + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-7", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "docs"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docs", "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "docs/README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "f-8", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "README"), []byte("bbb"), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "README").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Changes to the README").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("main", "f-7", "f-8", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + }) + + t.Run("Rebase", func(t *testing.T) { + // B + // / + // A--D + // \ + // C + // Where D is the base reference. + // B was rebased onto D, which produced C. + // B and D made different (non conflicting) changes to same file. + + // A commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "main-3", "main").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "REBASE"), bytes.Repeat([]byte{'b', 'b', 'b', '\n'}, 100), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "REBASE").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Rebasing is fun").Run(&RunOpts{Dir: tmpDir})) + + // B commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "g-1", "main-3").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "REBASE"), append(bytes.Repeat([]byte{'b', 'b', 'b', '\n'}, 100), 'a', 'a', 'a'), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "REBASE").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Rebasing is fun").Run(&RunOpts{Dir: tmpDir})) + + // D commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "g-2", "main-3").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "REBASE"), append([]byte{'a', 'a', 'a'}, bytes.Repeat([]byte{'b', 'b', 'b', '\n'}, 99)...), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "REBASE").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Rebasing is fun").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "g-3", "g-1").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "rebase", "g-2").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("g-2", "g-1", "g-3", nil) + require.NoError(t, err) + assert.True(t, changed) + }) + + t.Run("Rebasing change not shown", func(t *testing.T) { + // B + // / + // A--D + // \ + // C + // Where D is the base reference. + // B was rebased onto D, which produced C. + // B and D made different (non conflicting) changes to same file. + + // A commit + require.NoError(t, NewCommand(t.Context(), "switch", "--orphan", "main-4").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "A"), 0o700)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "A", "a"), bytes.Repeat([]byte{'A', 'A', 'A', '\n'}, 100), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "A/a").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Just wondering").Run(&RunOpts{Dir: tmpDir})) + + // B commit + // Changes last line. + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "h-1").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "A", "a"), append(bytes.Repeat([]byte{'A', 'A', 'A', '\n'}, 99), 'B', 'B', 'B', '\n'), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "A/a").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Just wondering").Run(&RunOpts{Dir: tmpDir})) + + // D commit + // Changes first line. + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "h-2", "main-4").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "A", "a"), append([]byte{'B', 'B', 'B', '\n'}, bytes.Repeat([]byte{'A', 'A', 'A', '\n'}, 99)...), 0o600)) + require.NoError(t, NewCommand(t.Context(), "add", "A/a").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "commit", "-m", "Just wondering").Run(&RunOpts{Dir: tmpDir})) + + // C commit + require.NoError(t, NewCommand(t.Context(), "switch", "-c", "h-3").Run(&RunOpts{Dir: tmpDir})) + require.NoError(t, NewCommand(t.Context(), "rebase", "h-2").Run(&RunOpts{Dir: tmpDir})) + + changed, err := gitRepo.CheckIfDiffDiffers("h-2", "h-1", "h-3", nil) + require.NoError(t, err) + + assert.False(t, changed) + }) +} diff --git a/modules/git/submodule.go b/modules/git/submodule.go index b99c81582b..4ea97d66eb 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -6,38 +6,124 @@ package git import ( "fmt" + "io" "net" "net/url" "path" "regexp" "strings" + + "forgejo.org/modules/setting" + "forgejo.org/modules/util" + + "gopkg.in/ini.v1" //nolint:depguard // used to read .gitmodules ) -var scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`) - -// SubModule submodule is a reference on git repository -type SubModule struct { - Name string - URL string -} - -// SubModuleFile represents a file with submodule type. -type SubModuleFile struct { - *Commit - - refURL string - refID string -} - -// NewSubModuleFile create a new submodule file -func NewSubModuleFile(c *Commit, refURL, refID string) *SubModuleFile { - return &SubModuleFile{ - Commit: c, - refURL: refURL, - refID: refID, +// GetSubmodule returns the Submodule of a given path +func (c *Commit) GetSubmodule(path string, entry *TreeEntry) (Submodule, error) { + err := c.readSubmodules() + if err != nil { + // the .gitmodules file exists but could not be read or parsed + return Submodule{}, err } + + sm, ok := c.submodules[path] + if !ok { + // no info found in .gitmodules: fallback to what we can provide + return Submodule{ + Path: path, + Commit: entry.ID, + }, nil + } + + sm.Commit = entry.ID + return sm, nil } +// readSubmodules populates the submodules field by reading the .gitmodules file +func (c *Commit) readSubmodules() error { + if c.submodules != nil { + return nil + } + + entry, err := c.GetTreeEntryByPath(".gitmodules") + if err != nil { + if IsErrNotExist(err) { + c.submodules = make(map[string]Submodule) + return nil + } + return err + } + + rc, _, err := entry.Blob().NewTruncatedReader(10 * 1024) + if err != nil { + return err + } + defer rc.Close() + + c.submodules, err = parseSubmoduleContent(rc) + return err +} + +func parseSubmoduleContent(r io.Reader) (map[string]Submodule, error) { + // https://git-scm.com/docs/gitmodules#_description + // The .gitmodules file, located in the top-level directory of a Git working tree + // is a text file with a syntax matching the requirements of git-config[1]. + // https://git-scm.com/docs/git-config#_configuration_file + + cfg := ini.Empty(ini.LoadOptions{ + InsensitiveKeys: true, // "The variable names are case-insensitive", but "Subsection names are case sensitive" + }) + err := cfg.Append(r) + if err != nil { + return nil, err + } + + sections := cfg.Sections() + submodule := make(map[string]Submodule, len(sections)) + + for _, s := range sections { + sm := parseSubmoduleSection(s) + if sm.Path == "" || sm.URL == "" { + continue + } + submodule[sm.Path] = sm + } + return submodule, nil +} + +func parseSubmoduleSection(s *ini.Section) Submodule { + section, name, _ := strings.Cut(s.Name(), " ") + if !util.ASCIIEqualFold("submodule", section) { // See https://codeberg.org/forgejo/forgejo/pulls/8438#issuecomment-5805251 + return Submodule{} + } + _ = name + + sm := Submodule{} + if key, _ := s.GetKey("path"); key != nil { + sm.Path = key.Value() + } + if key, _ := s.GetKey("url"); key != nil { + sm.URL = key.Value() + } + return sm +} + +// Submodule represents a parsed git submodule reference. +type Submodule struct { + Path string // path property + URL string // upstream URL + Commit ObjectID // upstream Commit-ID +} + +// ResolveUpstreamURL resolves the upstream URL relative to the repo URL. +func (sm Submodule) ResolveUpstreamURL(repoURL string) string { + repoFullName := strings.TrimPrefix(repoURL, setting.AppURL) // currently hacky, but can be dropped when refactoring getRefURL + return getRefURL(sm.URL, setting.AppURL, repoFullName, setting.SSH.Domain) +} + +var scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`) + func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string { if refURL == "" { return "" @@ -53,7 +139,7 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string { urlPrefix = strings.TrimSuffix(urlPrefix, "/") - // FIXME: Need to consider branch - which will require changes in modules/git/commit.go:GetSubModules + // FIXME: Need to consider branch - which will require changes in parseSubmoduleSection // Relative url prefix check (according to git submodule documentation) if strings.HasPrefix(refURI, "./") || strings.HasPrefix(refURI, "../") { return urlPrefix + path.Clean(path.Join("/", repoFullName, refURI)) @@ -107,13 +193,3 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string { return "" } - -// RefURL guesses and returns reference URL. -func (sf *SubModuleFile) RefURL(urlPrefix, repoFullName, sshDomain string) string { - return getRefURL(sf.refURL, urlPrefix, repoFullName, sshDomain) -} - -// RefID returns reference ID. -func (sf *SubModuleFile) RefID() string { - return sf.refID -} diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go index a396e4ea0d..2d27f47456 100644 --- a/modules/git/submodule_test.go +++ b/modules/git/submodule_test.go @@ -4,9 +4,11 @@ package git import ( + "strings" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGetRefURL(t *testing.T) { @@ -40,3 +42,74 @@ func TestGetRefURL(t *testing.T) { assert.Equal(t, kase.expect, getRefURL(kase.refURL, kase.prefixURL, kase.parentPath, kase.SSHDomain)) } } + +func Test_parseSubmoduleContent(t *testing.T) { + submoduleFiles := []struct { + fileContent string + expectedPath string + expected Submodule + }{ + { + fileContent: `[submodule "jakarta-servlet"] +url = ../../ALP-pool/jakarta-servlet +path = jakarta-servlet`, + expectedPath: "jakarta-servlet", + expected: Submodule{ + Path: "jakarta-servlet", + URL: "../../ALP-pool/jakarta-servlet", + }, + }, + { + fileContent: `[submodule "jakarta-servlet"] +path = jakarta-servlet +url = ../../ALP-pool/jakarta-servlet`, + expectedPath: "jakarta-servlet", + expected: Submodule{ + Path: "jakarta-servlet", + URL: "../../ALP-pool/jakarta-servlet", + }, + }, + { + fileContent: `[submodule "about/documents"] + path = about/documents + url = git@github.com:example/documents.git + branch = gh-pages +[submodule "custom-name"] + path = manifesto + url = https://github.com/example/manifesto.git +[submodule] + path = relative/url + url = ../such-relative.git +`, + expectedPath: "relative/url", + expected: Submodule{ + Path: "relative/url", + URL: "../such-relative.git", + }, + }, + { + fileContent: `# .gitmodules +# Subsection names are case sensitive +[submodule "Seanpm2001/Degoogle-your-life"] + path = Its-time-to-cut-WideVine-DRM/DeGoogle-Your-Life/submodule.gitmodules + url = https://github.com/seanpm2001/Degoogle-your-life/ + +[submodule "seanpm2001/degoogle-your-life"] + url = https://github.com/seanpm2001/degoogle-your-life/ +# This second section should not be merged with the first, because of casing +`, + expectedPath: "Its-time-to-cut-WideVine-DRM/DeGoogle-Your-Life/submodule.gitmodules", + expected: Submodule{ + Path: "Its-time-to-cut-WideVine-DRM/DeGoogle-Your-Life/submodule.gitmodules", + URL: "https://github.com/seanpm2001/Degoogle-your-life/", + }, + }, + } + for _, kase := range submoduleFiles { + submodule, err := parseSubmoduleContent(strings.NewReader(kase.fileContent)) + require.NoError(t, err) + v, ok := submodule[kase.expectedPath] + assert.True(t, ok) + assert.Equal(t, kase.expected, v) + } +} diff --git a/modules/git/tests/repos/templates_repo/COMMIT_EDITMSG b/modules/git/tests/repos/templates_repo/COMMIT_EDITMSG new file mode 100644 index 0000000000..a77fa514de --- /dev/null +++ b/modules/git/tests/repos/templates_repo/COMMIT_EDITMSG @@ -0,0 +1 @@ +Initial diff --git a/modules/git/tests/repos/templates_repo/HEAD b/modules/git/tests/repos/templates_repo/HEAD new file mode 100644 index 0000000000..cb089cd89a --- /dev/null +++ b/modules/git/tests/repos/templates_repo/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/modules/git/tests/repos/templates_repo/config b/modules/git/tests/repos/templates_repo/config new file mode 100644 index 0000000000..a4ef456cbc --- /dev/null +++ b/modules/git/tests/repos/templates_repo/config @@ -0,0 +1,5 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + logallrefupdates = true diff --git a/modules/git/tests/repos/templates_repo/description b/modules/git/tests/repos/templates_repo/description new file mode 100644 index 0000000000..498b267a8c --- /dev/null +++ b/modules/git/tests/repos/templates_repo/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/modules/git/tests/repos/templates_repo/index b/modules/git/tests/repos/templates_repo/index new file mode 100644 index 0000000000..2b3f95a155 Binary files /dev/null and b/modules/git/tests/repos/templates_repo/index differ diff --git a/modules/git/tests/repos/templates_repo/info/exclude b/modules/git/tests/repos/templates_repo/info/exclude new file mode 100644 index 0000000000..a5196d1be8 --- /dev/null +++ b/modules/git/tests/repos/templates_repo/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/modules/git/tests/repos/templates_repo/info/refs b/modules/git/tests/repos/templates_repo/info/refs new file mode 100644 index 0000000000..8ee4ab3ff8 --- /dev/null +++ b/modules/git/tests/repos/templates_repo/info/refs @@ -0,0 +1 @@ +45697427ce0595075c5c8efa42567f050208510d refs/heads/master diff --git a/modules/git/tests/repos/templates_repo/objects/info/commit-graph b/modules/git/tests/repos/templates_repo/objects/info/commit-graph new file mode 100644 index 0000000000..8904092586 Binary files /dev/null and b/modules/git/tests/repos/templates_repo/objects/info/commit-graph differ diff --git a/modules/git/tests/repos/templates_repo/objects/info/packs b/modules/git/tests/repos/templates_repo/objects/info/packs new file mode 100644 index 0000000000..5833126b59 --- /dev/null +++ b/modules/git/tests/repos/templates_repo/objects/info/packs @@ -0,0 +1,2 @@ +P pack-abb44544ae19d590e95822e963f78d069d27ba9e.pack + diff --git a/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.bitmap b/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.bitmap new file mode 100644 index 0000000000..6bd87bf13c Binary files /dev/null and b/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.bitmap differ diff --git a/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.idx b/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.idx new file mode 100644 index 0000000000..b530533e1b Binary files /dev/null and b/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.idx differ diff --git a/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.pack b/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.pack new file mode 100644 index 0000000000..6bbcbb6546 Binary files /dev/null and b/modules/git/tests/repos/templates_repo/objects/pack/pack-abb44544ae19d590e95822e963f78d069d27ba9e.pack differ diff --git a/modules/git/tests/repos/templates_repo/packed-refs b/modules/git/tests/repos/templates_repo/packed-refs new file mode 100644 index 0000000000..eb6e7a8add --- /dev/null +++ b/modules/git/tests/repos/templates_repo/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +45697427ce0595075c5c8efa42567f050208510d refs/heads/master diff --git a/modules/git/tests/repos/templates_repo/refs/heads/.gitkeep b/modules/git/tests/repos/templates_repo/refs/heads/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/git/tests/repos/templates_repo/refs/tags/.gitkeep b/modules/git/tests/repos/templates_repo/refs/tags/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/git/tree_blob.go b/modules/git/tree_blob.go index df339f64b1..5c1aa7753d 100644 --- a/modules/git/tree_blob.go +++ b/modules/git/tree_blob.go @@ -17,7 +17,6 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) { ptree: t, ID: t.ID, name: "", - fullName: "", entryMode: EntryModeTree, }, nil } @@ -55,7 +54,7 @@ func (t *Tree) GetBlobByPath(relpath string) (*Blob, error) { return nil, err } - if !entry.IsDir() && !entry.IsSubModule() { + if !entry.IsDir() && !entry.IsSubmodule() { return entry.Blob(), nil } diff --git a/modules/git/tree_entry.go b/modules/git/tree_entry.go index ec5c632ca0..8b6c4c467c 100644 --- a/modules/git/tree_entry.go +++ b/modules/git/tree_entry.go @@ -21,16 +21,12 @@ type TreeEntry struct { entryMode EntryMode name string - size int64 - sized bool - fullName string + size int64 + sized bool } // Name returns the name of the entry func (te *TreeEntry) Name() string { - if te.fullName != "" { - return te.fullName - } return te.name } @@ -68,8 +64,8 @@ func (te *TreeEntry) Size() int64 { return te.size } -// IsSubModule if the entry is a sub module -func (te *TreeEntry) IsSubModule() bool { +// IsSubmodule if the entry is a submodule +func (te *TreeEntry) IsSubmodule() bool { return te.entryMode == EntryModeCommit } @@ -214,7 +210,7 @@ func (te *TreeEntry) Tree() *Tree { // GetSubJumpablePathName return the full path of subdirectory jumpable ( contains only one directory ) func (te *TreeEntry) GetSubJumpablePathName() string { - if te.IsSubModule() || !te.IsDir() { + if te.IsSubmodule() || !te.IsDir() { return "" } tree, err := te.ptree.SubTree(te.Name()) @@ -241,7 +237,7 @@ type customSortableEntries struct { var sorter = []func(t1, t2 *TreeEntry, cmp func(s1, s2 string) bool) bool{ func(t1, t2 *TreeEntry, cmp func(s1, s2 string) bool) bool { - return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule() + return (t1.IsDir() || t1.IsSubmodule()) && !t2.IsDir() && !t2.IsSubmodule() }, func(t1, t2 *TreeEntry, cmp func(s1, s2 string) bool) bool { return cmp(t1.Name(), t2.Name()) diff --git a/modules/indexer/code/search.go b/modules/indexer/code/search.go index adf51a76d7..499b9117c4 100644 --- a/modules/indexer/code/search.go +++ b/modules/indexer/code/search.go @@ -97,7 +97,7 @@ func HighlightSearchResultCode(filename string, lineNums []int, highlightRanges conv := hcd.ConvertToPlaceholders(string(hl)) convLines := strings.Split(conv, "\n") - // each highlightRange is of the form [line number, start pos, end pos] + // each highlightRange is of the form [line number, start byte offset, end byte offset] for _, highlightRange := range highlightRanges { ln, start, end := highlightRange[0], highlightRange[1], highlightRange[2] line := convLines[ln] @@ -105,15 +105,18 @@ func HighlightSearchResultCode(filename string, lineNums []int, highlightRanges continue } + sr := strings.NewReader(line) sb := strings.Builder{} count := -1 isOpen := false - for _, r := range line { + for r, size, err := sr.ReadRune(); err == nil; r, size, err = sr.ReadRune() { if token, ok := hcd.PlaceholderTokenMap[r]; // token was not found - !ok || - // token was marked as used - token == "" || + !ok { + count += size + } else if + // token was marked as used + token == "" || // the token is not an valid html tag emitted by chroma !(len(token) > 6 && (token[0:5] == "= end: // if tag is not open, no need to close if !isOpen { break } sb.WriteRune(endTag) isOpen = false - case start: + case count >= start: // if tag is open, do not open again if isOpen { break @@ -161,7 +164,7 @@ func HighlightSearchResultCode(filename string, lineNums []int, highlightRanges highlightedLines := strings.Split(hcd.Recover(conv), "\n") // The lineNums outputted by highlight.Code might not match the original lineNums, because "highlight" removes the last `\n` lines := make([]ResultLine, min(len(highlightedLines), len(lineNums))) - for i := 0; i < len(lines); i++ { + for i := range len(lines) { lines[i].Num = lineNums[i] lines[i].FormattedContent = template.HTML(highlightedLines[i]) } diff --git a/modules/indexer/code/search_test.go b/modules/indexer/code/search_test.go new file mode 100644 index 0000000000..e542b38c24 --- /dev/null +++ b/modules/indexer/code/search_test.go @@ -0,0 +1,122 @@ +// Copyright 2025 The Forgejo Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package code + +import ( + "html/template" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestHighlightSearchResultCode(t *testing.T) { + opts := []struct { + Title string + File string + Lines []int + Range [][3]int + Code string + Result []template.HTML + }{ + { + Title: "One Match Text", + File: "test.txt", + Range: [][3]int{{1, 5, 9}}, + Code: "First Line\nMark this only\nThe End", + Result: []template.HTML{ + "First Line", + "Mark this only", + "The End", + }, + }, + { + Title: "Two Match Text", + File: "test.txt", + Range: [][3]int{ + {1, 5, 9}, + {2, 5, 9}, + }, + Code: "First Line\nMark this only\nMark this too\nThe End", + Result: []template.HTML{ + "First Line", + "Mark this only", + "Mark this too", + "The End", + }, + }, + { + Title: "Unicode Before", + File: "test.txt", + Range: [][3]int{{1, 10, 14}}, + Code: "First Line\nMark 👉 this only\nThe End", + Result: []template.HTML{ + "First Line", + "Mark 👉 this only", + "The End", + }, + }, + { + Title: "Unicode Between", + File: "test.txt", + Range: [][3]int{{1, 5, 14}}, + Code: "First Line\nMark this 😊 only\nThe End", + Result: []template.HTML{ + "First Line", + "Mark this 😊 only", + "The End", + }, + }, + { + Title: "Unicode Before And Between", + File: "test.txt", + Range: [][3]int{{1, 10, 19}}, + Code: "First Line\nMark 👉 this 😊 only\nThe End", + Result: []template.HTML{ + "First Line", + "Mark 👉 this 😊 only", + "The End", + }, + }, + { + Title: "Golang", + File: "test.go", + Range: [][3]int{{1, 14, 23}}, + Code: "func main() {\n\tfmt.Println(\"mark this\")\n}", + Result: []template.HTML{ + "func main() {", + "\tfmt.Println("mark this")", + "}", + }, + }, + { + Title: "Golang Unicode", + File: "test.go", + Range: [][3]int{{1, 14, 28}}, + Code: "func main() {\n\tfmt.Println(\"mark this 😊\")\n}", + Result: []template.HTML{ + "func main() {", + "\tfmt.Println("mark this 😊")", + "}", + }, + }, + } + for _, o := range opts { + t.Run(o.Title, func(t *testing.T) { + lines := []int{} + for i := range strings.Count(strings.TrimSuffix(o.Code, "\n"), "\n") + 1 { + lines = append(lines, i+1) + } + res := HighlightSearchResultCode(o.File, lines, o.Range, o.Code) + assert.Len(t, res, len(o.Result)) + assert.Len(t, res, len(lines)) + + for i, r := range res { + require.Equal(t, lines[i], r.Num) + require.Equal(t, o.Result[i], r.FormattedContent) + } + }) + } +} diff --git a/modules/storage/minio.go b/modules/storage/minio.go index bf51a1642a..424000a0d8 100644 --- a/modules/storage/minio.go +++ b/modules/storage/minio.go @@ -209,7 +209,7 @@ func (m *MinioStorage) Save(path string, r io.Reader, size int64) (int64, error) m.ctx, m.bucket, m.buildMinioPath(path), - r, + io.NopCloser(r), // prevent minio from closing the reader size, minio.PutObjectOptions{ ContentType: "application/octet-stream", diff --git a/modules/storage/storage_test.go b/modules/storage/storage_test.go index af3dd9520e..76589d941a 100644 --- a/modules/storage/storage_test.go +++ b/modules/storage/storage_test.go @@ -5,6 +5,7 @@ package storage import ( "bytes" + "io" "testing" "forgejo.org/modules/setting" @@ -13,22 +14,39 @@ import ( "github.com/stretchr/testify/require" ) +type spyCloser struct { + io.Reader + closed int +} + +func (s *spyCloser) Close() error { + s.closed++ + return nil +} + +var _ io.ReadCloser = &spyCloser{} + func testStorageIterator(t *testing.T, typStr Type, cfg *setting.Storage) { l, err := NewStorage(typStr, cfg) require.NoError(t, err) - testFiles := [][]string{ - {"a/1.txt", "a1"}, - {"/a/1.txt", "aa1"}, // same as above, but with leading slash that will be trim - {"ab/1.txt", "ab1"}, - {"b/1.txt", "b1"}, - {"b/2.txt", "b2"}, - {"b/3.txt", "b3"}, - {"b/x 4.txt", "bx4"}, + testFiles := []struct { + path, content string + size int64 + }{ + {"a/1.txt", "a1", -1}, + {"/a/1.txt", "aa1", -1}, // same as above, but with leading slash that will be trim + {"ab/1.txt", "ab1", 3}, + {"b/1.txt", "b1", 2}, // minio closes when the size is set + {"b/2.txt", "b2", -1}, + {"b/3.txt", "b3", -1}, + {"b/x 4.txt", "bx4", -1}, } for _, f := range testFiles { - _, err = l.Save(f[0], bytes.NewBufferString(f[1]), -1) + sc := &spyCloser{bytes.NewBufferString(f.content), 0} + _, err = l.Save(f.path, sc, f.size) require.NoError(t, err) + assert.Equal(t, 0, sc.closed) } expectedList := map[string][]string{ diff --git a/options/locale/locale_ar.ini b/options/locale/locale_ar.ini index ba11586b44..638c2dc6ce 100644 --- a/options/locale/locale_ar.ini +++ b/options/locale/locale_ar.ini @@ -50,7 +50,7 @@ concept_user_organization = المنظمة link_account = ربط الحساب rerun_all = أعِد تشغيل جميع الوظائف your_profile = الملف الشخصي -sign_out = سجل الخروج +sign_out = سجّل الخروج settings = الإعدادات locked = مقفول error = خطأ @@ -87,7 +87,7 @@ add_all = أضف الكل new_fork = اشتقاق جديد لمستودع new_project_column = عمود جديد add = أضف -active_stopwatch = تتبع وقت الإنجاز +active_stopwatch = متتبِّع وقت النشاط organization = منظمة new_migrate = ترحيل جديد save = احفظ @@ -114,7 +114,7 @@ twofa_scratch = الرمز الاحتياطي للمصادقة بعاملين home = الرئيسية email = عنوان البريد الإلكتروني issues = المسائل -error404 = الصفحة التي تحاول الوصول لها إما لا توجد أو أنت لست مأذون لك بعرضها. +error404 = الصفحة التي تحاول الوصول لها إما غير موجودو أو أنك غير مصرح لك بعرضها. powered_by = مدعوم بواسطة %s retry = أعد المحاولة tracked_time_summary = ملخص للتتبع الزمني وفقًا لنتائج تصفية قائمة المسائل @@ -127,8 +127,8 @@ toggle_menu = تبديل القائمة more_items = عناصر اضافية copy_generic = نسخ إلى الحافظة invalid_data = بيانات غير صالحة: %v -filter.clear = مسح المرشحات -filter = مرشح +filter.clear = مسح عوامل التصفية +filter = عامل تصفية filter.is_archived = مؤرشف filter.is_template = قوالب filter.not_mirror = ليست مرايا @@ -137,13 +137,17 @@ filter.is_mirror = مرايا filter.is_fork = الاشتقاقات filter.not_fork = ليست اشتقاقات filter.not_archived = ليس مؤرشف -filter.public = علني +filter.public = عام filter.private = خاص new_repo.title = مستودع جديد new_migrate.title = انتقال جديد new_org.title = منظمة جديدة new_repo.link = مستودع جديد new_migrate.link = انتقال جديد +copy_path = نسخ المسار +test = اختبار +new_org.link = منظمة جديدة +error413 = لقد استنفدت حصتك. [install] db_name = اسم قاعدة البيانات @@ -170,7 +174,7 @@ reinstall_confirm_check_2 = وقد يلزم إعادة تزامن المستود run_user = شغّل عبر مستخدم err_admin_name_is_invalid = اسم مستخدم المدير غير صالح reinstall_confirm_check_3 = أنتِ تؤكد أنكِ متأكد تماماً من أن فورجيو يعمل مع مسار app.ini الصحيح وأنك متأكد من أنه يجب عليك إعادة تثبيته. أنت تُؤكّدُ بأنّك تُقرّ بالمخاطر السالفة الذكر. -repo_path = المسار الجذري للمستودع +repo_path = المسار الجذر للمستودع err_empty_admin_email = عنوان بريد المدير لا يمكن أن يكون فارغ. no_admin_and_disable_registration = لا يمكنك تعطيل التسجيل الذاتي للمستخدمين بدون إنشاء حساب إداري. err_admin_name_pattern_not_allowed = اسم مستخدم المدير غير صالح، هذا الأسم يطابق نمطا محجوز @@ -179,10 +183,10 @@ repo_path_helper = ستُحفظ كلّ مستودعات جِت البعيدة ف general_title = الإعدادات العامة lfs_path_helper = الملفات التي تم تعقبها بواسطة Git LFS ستُخزن في هذا الدليل. اتركه فارغًا لتعطيله. err_empty_db_path = طريق قاعدة بيانات SQLite3 لا يمكن أن يكون فارغا. -lfs_path = مسار جذر جِت LFS -app_name_helper = يمكنك إدخال اسم شركتك هنا. +lfs_path = مسار جذر Git LFS +app_name_helper = أدخل اسم المثيل هنا. سيظهر هذا الاسم في كل الصفحات. err_admin_name_is_reserved = اسم مستخدم المدير غير صالح، هذا الأسم محجوز -app_name = عنوان الموقع +app_name = عنوان المثيل log_root_path = مسار السجل log_root_path_helper = ستُكتب ملفات السجل في هذا الدليل. smtp_addr = مضيف SMTP @@ -190,7 +194,7 @@ smtp_port = منفذ SMTP mailer_password = كلمة مرور SMTP app_url_helper = العنوان الأساسي لاستنساخ عناوين URL HTTP(S) وإشعارات البريد الإلكتروني. mailer_user = اسم مستخدم SMTP -disable_gravatar.description = عطل جرافاتار والجهات الخارجية للصور الرمزية. ستُستخدم صورة رمزية مبدئية حتى يرفع المستخدم صورة. +disable_gravatar.description = عطل Gravatar والجهات الخارجية للصور الرمزية. ستُستخدم صورة رمزية مبدئية حتى يرفع المستخدم صورة. offline_mode.description = عطل خدمات توصيل المحتوى من الجهات الخارجية، واخدم كل المحتوى محلياً. run_user_helper = اسم مستخدم نظام التشغيل الذي يشغل فورجيو. ملاحظة: هذا المستخدم يجب أن يكون له حق الوصول إلى المسار الجذري للمستودع. domain = نطاق الخادم @@ -199,28 +203,28 @@ smtp_from = أرسل البريد الإلكتروني كـ federated_avatar_lookup = تفعيل الصور الرمزية الاتحادية optional_title = إعدادات اختيارية domain_helper = نطاق أو عنوان المضيف لخادمك. -mail_notify = فعّل التنبيه عبر البريد الإلكتروني -app_url = الرابط الأساس لفورجيو +mail_notify = فعّل التنبيهات عبر البريد الإلكتروني +app_url = الرابط الأساس smtp_from_helper = عنوان البريد الإلكتروني الذي سيستخدمه فورجيو. أدخل عنوان بريد إلكتروني عادي أو استخدم صيغة"Name" . ssh_port_helper = رقم المنفذ الذي يستمع له خادم SSH. اتركه فارغاً لتعطيله. -http_port_helper = المنفذ الذي سيستمع إليه خادم الويب لفورجيو. -http_port = منفذ استماع HTTP لفورجيو +http_port_helper = المنفذ الذي سيستمع إليه خادم ويب Forgejo. +http_port = منفذ استماع HTTP ssh_port = منفذ خادم SSH email_title = إعدادات البريد الإلكتروني offline_mode = فعل الوضع المحلي server_service_title = إعدادات الخادم وخدمات الجهات الخارجية register_confirm = الزم تأكيد البريد الإلكتروني للتسجيل -allow_only_external_registration.description = لا يسمح بالتسجيل إلا من خلال الخدمات الخارجية +allow_only_external_registration.description = لن يتمكن المستخدمون من إنشاء حسابات جديدة إلا باستخدام خدمات خارجية مهيأة. disable_registration = عطّل التسجيل الذاتي -federated_avatar_lookup.description = تفعيل الصور الرمزية الاتحادية باستخدام ليبرافاتار. +federated_avatar_lookup.description = تفعيل الصور الرمزية الاتحادية باستخدام Libravatar. openid_signup = فعّل التسجيل الذاتي عبر OpenID -disable_registration.description = عطل التسجيل الذاتي. المديرون فقط سيكونون قادرين على إنشاء حسابات جديدة للمستخدمين. +disable_registration.description = سيتمكن مسؤولو المثيل فقط من إنشاء حسابات مستخدمين جديدة. يوصى بشدة بإبقاء التسجيل معطلاً إلا إذا كنت تنوي استضافة مثيل عام للجميع ومستعد للتعامل مع كميات كبيرة من الحسابات غير المرغوب بها. openid_signin = فعّل تسجيل الدخول عبر OpenID openid_signin.description = فعّل تسجيل دخول المستخدمين عبر OpenID. enable_captcha = فعّل كابتشا التسجيل -enable_captcha.description = الزم وجود كابتشا للتسجيل الذاتي للمستخدمين. +enable_captcha.description = مطالبة المستخدمين باجتياز اختبار CAPTCHA من أجل إنشاء حسابات. openid_signup.description = فعّل التسجيل الذاتي للمستخدمين عبر OpenID. -require_sign_in_view = الزم تسجيل الدخول لعرض الصفحات +require_sign_in_view = يتطلب تسجيل الدخول لعرض محتوى المثيل require_sign_in_view.description = مكّن وصول الصفحات للمستخدمين فقط. لن يرى الزائرون سوى صفحات التسجيل والتسجيل. admin_setting.description = إنشاء حساب إداري هو اختياري. أول مستخدم مُسجل سيصبح تلقائيا مديرا. admin_password = كلمة المرور @@ -233,7 +237,7 @@ test_git_failed = يتعذر اختبار أمر جِت: %v confirm_password = أكّد كلمة المرور invalid_admin_setting = إعداد حساب المدير غير صالح: %v invalid_log_root_path = مسار السجل غير صالح: %v -default_enable_timetracking = فعّل تتبع الوقت مبدئيا +default_enable_timetracking = فعّل التتبع الزمني افتراضيًا env_config_keys_prompt = ستطبق المتغيرات البيئية التالية أيضاً على ملف الإعدادات: admin_title = إعدادات حساب المدير no_reply_address_helper = النطاق للمستخدمين بعنوان بريد إلكتروني مخفي. مثلاً، اسم المستخدم "sarah" سوف يسجل في جِت كـ"sarah@noreply.example.org" لو كان نطاق البريد الإلكتروني الخفي مدخل كـ"noreply.example.org". @@ -242,9 +246,9 @@ default_enable_timetracking.description = فعل تتبع الوقت للمست run_user_not_match = مستخدم التشغيل غير مطابق لأسم المستخدم الحالي: %s -> %s invalid_db_setting = إعدادات قاعدة البيانات غير صالحة: %v invalid_db_table = جدول قاعدة البيانات "%s" غير صالح: %v -default_keep_email_private.description = أخفِ عناوين البريد الإلكتروني للحسابات الجديدة مبدئيا. +default_keep_email_private.description = قم بتمكين إخفاء عنوان البريد الإلكتروني للمستخدمين الجدد افتراضيًا حتى لا يتم تسريب هذه المعلومات فور التسجيل. env_config_keys = إعدادات بيئية -default_allow_create_organization = اسمح بإنشاء المنظمات مبدئيا +default_allow_create_organization = اسمح بإنشاء المنظمات بشكل افتراضي invalid_app_data_path = مسار بيانات التطبيق غير صالح: %v enable_update_checker_helper = يفحص لإيجاد اصدارات جديدة عن طريق الإتصال بسيرفرات فورجيو. invalid_repo_path = المسار الجزري للمستودع غير صالح: %v @@ -252,10 +256,15 @@ internal_token_failed = فشل توليد الرمز الداخلي: %v no_reply_address = نطاقات البريد الإلكتروني المخفية default_keep_email_private = أخفِ عناوين البريد الإلكتروني مبدئيا admin_name = اسم مستخدم المدير -default_allow_create_organization.description = اسمح بحسابات المستخدمين الجديدة بإنشاء المنظمات مبدئيا. +default_allow_create_organization.description = السماح للمستخدمين الجدد بإنشاء منتديات المجموعة بشكل افتراضي. عند تعطيل هذا الخيار، سيتعين على المسؤول منح إذن لإنشاء منتديات المجموعة للمستخدمين الجدد. password_algorithm = خوارزمية تجزئة كلمة المرور invalid_password_algorithm = خوارزمية بصمة كلمة المرور غير صالحة password_algorithm_helper = اختر خوارزمية بصمة كلمة المرور. تختلف الخوارزميات في متطلباتها وقوتها. خوارزمية argon2 آمنة لكن تتطلب الكثير من الذاكرة ولذلك قد تكون غير ملائمة للأنظمة الصغيرة. +app_slogan_helper = أدخل شعار المثيل الخاص بك هنا. اتركه فارغاً لتعطيله. +app_slogan = شعار المثيل +allow_only_external_registration = السماح بالتسجيل عبر الخدمات الخارجية فقط +config_location_hint = سيتم حفظ خيارات التهيئة هذه في: +smtp_from_invalid = عنوان "،بريد الإرسال كـ" غير صالح [editor] buttons.list.ordered.tooltip = أضف قائمة مرقمة @@ -272,10 +281,22 @@ buttons.mention.tooltip = اذكر مستخدمًا أو فريقًا buttons.italic.tooltip = أضف نصًا مائلًا buttons.link.tooltip = اضف رابط buttons.disable_monospace_font = عطّل الخط الثابت العرض +buttons.unindent.tooltip = ‪عناصر غير متساوية من نفس المستوى +buttons.indent.tooltip = تداخل العناصر بنفس المستوى +table_modal.header = إضافة جدول +table_modal.placeholder.header = الترويسة +table_modal.placeholder.content = المحتوى +table_modal.label.rows = الصفوف +table_modal.label.columns = الأعمدة +link_modal.url = Url +link_modal.description = الوصف +buttons.new_table.tooltip = إضافة جدول +link_modal.header = إضافة رابط +link_modal.paste_reminder = تلميح: باستخدام عنوان URL في حافظتك، يمكنك اللصق مباشرةً في المحرر لإنشاء رابط. [aria] navbar = شريط التنقل -footer.software = عن البرمجية +footer.software = عن هذه البرمجية footer.links = روابط footer = الذيل @@ -1386,6 +1407,21 @@ repo.transfer.subject_to = %s يود نقل ملكية "%s" إلى %s issue.action.ready_for_review = @%[1]s علّم هذا الطلب للسحب كجاهز للمراجعة. issue_assigned.pull = @%[1]s عيّنك إلى طلب سحب %[2]s في مستودع %[3]s. issue.action.review_dismissed = @%[1]s أستبعد آخر مراجعة من %[2]s لهذا الطلب للسحب. +password_change.subject = تم تغيير كلمة مرورك +totp_disabled.subject = تم تعطيل TOTP +totp_disabled.text_1 = تم تعطيل كلمة المرور لمرة واحدة المستندة إلى الوقت (TOTP) على حسابك للتو. +totp_enrolled.text_1.has_webauthn = لقد قمت للتو بتمكين TOTP لحسابك. هذا يعني أنه بالنسبة لجميع عمليات تسجيل الدخول المستقبلية إلى حسابك، يمكنك استخدام TOTP كطريقة للمصادقة الثنائية ، أو استخدام أي من مفاتيح الأمان الخاصة بك. +totp_enrolled.subject = لقد قمت بتشيط TOTP كطريقة 2FA +removed_security_key.subject = تمت إزالة مفتاح الأمان +removed_security_key.text_1 = تم إزالة مفتاح الأمان ”%[1] s“ للتو من حسابك. +account_security_caution.text_1 = إذا كان هذا أنت، فيمكنك تجاهل هذا البريد بأمان. +totp_disabled.no_2fa = لم تعد هناك طرق أُخرى للمصادقة الثنائية (2FA) قيد التهيئة عد الآن ، أي أنه لم يعد من الضروري تسجيل الدخول إلى حسابك باستخدام المصادقة الثنائية (2FA). +removed_security_key.no_2fa = لم تعد هناك طرق أخرى للمصادقة الثنائية (2FA) قيد التهيئة بعد الآن، أي لم يعد من الضروري تسجيل الدخول إلى حسابك باستخدام المصادقة الثنائية (2FA). +primary_mail_change.subject = تم تغيير البريد الأساسي الخاص بك +password_change.text_1 = تم تغيير كلمة مرور حسابك للتو. +primary_mail_change.text_1 = تم تغيير البريد الإلكتروني الأساسي لحسابك إلى %[1]s. هذا يعني أن عنوان البريد الإلكتروني هذا لن يتلقى إشعارات البريد لحسابك بعد الآن. +account_security_caution.text_2 = إذا لم تكن أنت، فهذا يعني أن حسابك مخترق. يرجى الاتصال بمسؤولي هذا الموقع. +totp_enrolled.text_1.no_webauthn = لقد قمت للتو بتمكين TOTP لحسابك. هذا يعني أنه بالنسبة لجميع عمليات تسجيل الدخول المستقبلية إلى حسابك، يجب عليك استخدام TOTP كطريقة للمصادقة الثنائية. [error] not_found = تعذر العثور على الهدف. @@ -1421,7 +1457,7 @@ joined_on = انضم في %s user_bio = السيرة الذاتية repositories = المستودعات activity = النشاط العام -projects = مشاريع +projects = المشاريع unfollow = إلغِ المتابعة settings = إعدادات المستخدم following_few = %d يتابع @@ -1429,7 +1465,7 @@ follow = تابع followers_few = %d متابعين form.name_reserved = اسم المستخدم "%s" محجوز. email_visibility.limited = عنوان بريدك الإلكتروني ظاهر لكل المستخدمين المُستَوثَقين -code = البرمجية +code = الكود overview = نظرة عامة watched = المستودعات المشاهدة disabled_public_activity = هذا المستخدم عطّل الظهور العام للنشاط. @@ -1438,6 +1474,17 @@ email_visibility.private = عنوان بريدك الإلكتروني ظاهر starred = المستودعات المميّزة بنجمة form.name_chars_not_allowed = اسم المستخدم "%s" يحتوي على رموز غير صالحة. form.name_pattern_not_allowed = النمط "s%" غير مسموح به في إسم المستخدم. +followers.title.one = متابِع +public_activity.visibility_hint.admin_private = هذا النشاط مرئي لك لأنك مسؤول، ولكن المستخدم يريد أن يظل خاصاً. +public_activity.visibility_hint.self_private = نشاطك مرئي لك ولسُعاة المثيل فقط. تعديل الإعدادات. +followers_one = %d متابِع +following.title.one = متابعة +followers.title.few = متابعين +following_one = %d يُتابع +following.title.few = متابعة +public_activity.visibility_hint.self_public = نشاطك مرئي للجميع، باستثناء التفاعلات في المساحات الخاصة. اضبط الإعدادات. +public_activity.visibility_hint.admin_public = هذا النشاط مرئي للجميع، ولكن بصفتك مسؤولاً يمكنك أيضًا رؤية التفاعلات في المساحات الخاصة. +public_activity.visibility_hint.self_private_profile = نشاطك مرئي لك ولسُعاة المثيل فقط لأن ملفك الشخصي خاص. تعديل الإعدادات. [auth] change_unconfirmed_email_error = تعذر تغيير البريد الإلكتروني: %v @@ -1458,11 +1505,11 @@ active_your_account = فعّل حسابك register_helper_msg = هل لديك حساب بالفعل؟ سجل الدخول! manual_activation_only = تواصل مع مدير موقعك لإكمال التفعيل. must_change_password = حدّث كلمة المرور الخاصة بك -send_reset_mail = أرسل رسالة استعادة حساب +send_reset_mail = أرسل بريد الاستعادة resend_mail = اضغط هنا لإعادة إرسالة رسالة تفعيل حسابك has_unconfirmed_mail = أهلا يا %s، لديك عنوان بريد إلكتروني غير مؤكَّد (%s). إن لم تستلم رسالة تأكيد أو تريد إرسال واحدة جديدة، فنرجو الضغط على الزر الذي بالأسفل. email_not_associate = عنوان البريد هذا غير مرتبط بأي حساب. -reset_password = استعادة حساب +reset_password = استعادة الحساب oauth_signin_tab = أربط بحساب موجود invalid_password = كلمة المرور الخاصة بك لا تطابق كلمة المرور التي استخدمت لتسجيل الحساب. oauth_signin_title = سجّل الدخول لتأذن للحساب المربوط @@ -1483,13 +1530,13 @@ reset_password_wrong_user = أنت مُسجل كـ %s، لكن رابط أعاد openid_connect_title = اتصل بحساب موجود confirmation_mail_sent_prompt = تم إرسال بريد تأكيد جديد إلى %s. يرجى التأكد من صندوق بريدك في خلال %s حتى تكتمل عملية التسجيل. إذا كان عنوان البريد خاطئ، يمكنك تسجيل الدخول وطلب بريد تأكيد جديد يُرسل إلى عنوان آخر. scratch_code = رمز الخدش -invalid_code_forgot_password = رمز تأكيدك غير صحيح أو انتهى اضغط هنا للإعادة. +invalid_code_forgot_password = رمز تأكيدك غير صحيح أو انتهت صلاحيته. اضغط هنا للإعادة. openid_register_title = أنشئ حسابًا جديدًا verify = تحقق twofa_scratch_used = لقد استخدمت رمز الخدش الخاص بك. لقد تم إعادة توجيهك إلى إعدادات المصادقة الثنائية حتى يمكنك إزالة تسجيل جهازك أو توليد رمز خدش جديد. oauth_signup_submit = أكمل الحساب oauth.signin.error = كان هناك خطأ في تجهيز طلب الإذن إذا استمر هذا الخطأ، يرجى الاتصال بالمدير. -invalid_code = رمز تأكيدك غير صحيح أو انتهى. +invalid_code = رمز تأكيدك غير صحيح أو انتهت صلاحيته. oauth_signup_title = أكمل حساب جديد resent_limit_prompt = لقد طلبت بالفعل بريداً إلكترونياً للتفعيل مؤخراً من فضلك انتظر 3 دقائق وحاول مرة أخرى. reset_password_mail_sent_prompt = تم إرسال بريد تأكيد جديد إلى %s. يرجى التأكد من صندوق بريدك في خلال %s حتى تكتمل عملية استعادة الحساب. @@ -1513,6 +1560,13 @@ openid_register_desc = مسار الـOpenID المختار مجهول. اربط remember_me = تذكر هذا الجهاز remember_me.compromised = رمز الاحتفاظ بتسجيل الدخول لم يعد صالحا، مما قد يعني اختراق الحساب. نرجو مراجعة حسابك لرؤية أي نشاط غير مألوف. authorization_failed_desc = فشل التفويض لأننا اكتشفنا طلبًا غير صالح. يرجى الاتصال بمشرف التطبيق الذي حاولت ترخيصه. +sign_in_openid = المتابعة باستخدام OpenID +hint_login = لديك حساب بالفعل؟ سجّل الدخول الآن! +hint_register = يلزمك حساب ؟ سجِّل الآن. +sign_up_button = سجِّل الآن. +back_to_sign_in = العودة إلى تسجيل الدخول +use_onetime_code = استخدم رمزًا لمرة واحدة +unauthorized_credentials = بيانات الاعتماد غير صحيحة أو انتهت صلاحيتها. أعد محاولة تنفيذ الأمر أو راجع %s لمزيد من المعلومات [packages] rpm.repository.multiple_groups = هذه الحزمة متوفرة في مجموعات متعددة. @@ -1556,6 +1610,9 @@ less = أقل number_of_contributions_in_the_last_12_months = %s مساهم في آخر 12 شهر contributions_zero = بلا مساهمات more = أكثر +contributions_format = {contributions} مساهمة في {day} {month} {year} +contributions_one = المساهمة +contributions_few = المساهمات [admin] self_check.database_fix_mysql = لمستخدمين ميسكول/ماريا دي بي، يمكنك استخدام أمر "forgejo doctor convert" لإصلاح مشاكل التجمّع، أو يمكنك أيضاً إصلاح المشكلة عن طريق تعديل السيكول يدوياً. @@ -1707,7 +1764,7 @@ enterred_invalid_org_name = اسم المنظمة التي أدخلته خطأ. lang_select_error = اختر لغة من القائمة. alpha_dash_error = ` لا يجب أن يحتوي إلا على الحروف الإنجليزية والأرقام والشرطة ("-") والشرطة السفلية ("_").` alpha_dash_dot_error = ` لا يجب أن يحتوي إلا على الحروف الإنجليزية والأرقام والشرطة ("-") والشرطة السفلية ("_") والنقطة (".").` -repo_name_been_taken = اسم المستودع مستعمل بالفعل. +repo_name_been_taken = اسم المستودع مستخدم بالفعل. Email = البريد الإلكتروني auth_failed = فشل الاستيثاق: %v email_error = ` ليس عنوان بريد إلكتروني صالح.` @@ -1727,10 +1784,10 @@ still_has_org = "حسابك عضو في منظمة أو أكثر؛ غادرهم repository_files_already_exist.adopt_or_delete = الملفات موجودة بالفعل لهذا المستودع. إما اعتمادها أو حذفها. repository_files_already_exist.delete = الملفات موجودة بالفعل لهذا المستودع. يجب عليك حذفها. repository_files_already_exist.adopt = الملفات موجودة بالفعل لهذا المستودع ويمكن اعتمادها فقط. -repository_files_already_exist = الملفات موجودة بالفعل لهذا المستودع. تواصل مع مدير النظام. +repository_files_already_exist = الملفات موجودة بالفعل لهذا المستودع. اتصل بمدير النظام. TeamName = اسم الفريق username_has_not_been_changed = لم يتم تغيير اسم المستخدم -username_change_not_local_user = المستخدمين غير المحليين غير مسموح لهم بتغيير أسماؤهم. +username_change_not_local_user = المستخدمين غير المحليين غير مسموح لهم بتغيير أسمائهم. captcha_incorrect = الكابتشا خاطئة. AdminEmail = عنوان البريد الإلكتروني للمدير team_no_units_error = اسمح بالوصول إلى قسم واحد على الأقل في المستودعات. @@ -1757,6 +1814,23 @@ glob_pattern_error = `النمط الشامل غير صالح: %s.` CommitChoice = إختيار الإداع regex_pattern_error = ` نمط التعبير النمطي غير صالح: %s.` username_error = ` يُمكنه أن يحتوي على حروف إنجليزية وأرقام وشرطة ("-") وشرطة سفلية ("_") و نقطة (".") فقط. ويمكنه ان يبدأ وينتهي بحرف او برقم.` +Biography = النبذة +Website = موقع الويب +To = اسم الفرع +AccessToken = رمز الوصول +repository_force_private = وضع الخاص الإجباري مفعّل: لا يمكن تحويل المستودعات الخاصة إلى عامة. +FullName = الاسم الكامل +Description = الوصف +Pronouns = الضمائر +username_claiming_cooldown = لا يمكن المطالبة باسم المستخدم، لأن فترة تباطؤه لم تنتهِ بعد. يمكن المطالبة به عند %[1]s. +Location = الموقع +invalid_group_team_map_error = ` التعيين غير صالح: %s ` +visit_rate_limit = تناولت الزيارة عن بُعد الحد من معدلها. +email_domain_is_not_allowed = نطاق البريد الإلكتروني للمستخدم %s يتعارض مع قائمة النطاقات المسموحة ، أو الممنوعة. يرجى التأكد من إدخال عنوان البريد الإلكتروني بشكل صحيح. +unset_password = المستخدم المسجل لم يقم بتعيين كلمة مرور. +unsupported_login_type = نوع تسجيل الدخول غير مدعوم لحذف الحساب. +invalid_ssh_principal = أصل غير صالح: %s +required_prefix = المُدخل يجب أن يبدأ مع "%s" [home] filter = تصفيات أخرى @@ -1803,6 +1877,10 @@ code_no_results = لم يتم العثور على برمجية تطابق الب relevant_repositories_tooltip = تم أخفاء المستودعات التي هي مشتقات وأيضاً التي ليس لها موضوع، ولا أيقونة، ولا يوجد وصف. relevant_repositories = يتم اظهار المستودعات المتعلقة فقط. أظهر النتائج غير المصفاة. code_last_indexed_at = فُهرس آخر مرة %s +stars_few = %d نجوم +forks_one = %d نسخة +forks_few = %d نُسَخ +stars_one = %d نجمة [actions] variables.none = لا توجد متغيرات بعد. @@ -1976,7 +2054,7 @@ component_failed_to_load = حدث خطأ غير متوقع. [search] org_kind = بحث في المنظمات… code_search_unavailable = البحث في الكود غير متوفر حاليًا. يرجى الاتصال بمدير الموقع. -search = ابحث... +search = البحث… type_tooltip = نوع البحث fuzzy = أجعد fuzzy_tooltip = قم بتضمين النتائج التي تتطابق أيضًا مع مصطلح البحث بشكل وثيق @@ -1985,10 +2063,19 @@ match_tooltip = قم بتضمين النتائج التي تطابق مصطلح repo_kind = بحث في المستودعات… user_kind = بحث عن المستخدمين… team_kind = بحث عن الفرق… -code_kind = بحث في الكود… +code_kind = بحث ضمن الكود… project_kind = البحث ضمن المشاريع… branch_kind = البحث ضمن الفروع… no_results = لا توجد نتائج مطابقة. issue_kind = البحث ضمن الأعطال… pull_kind = البحث ضمن طلبات السحب… keyword_search_unavailable = البحث من خلال الكلمات المفتاحية ليس متوفر حالياً. رجاءاً تواصل مع مشرف الموقع. +package_kind = البحث ضمن الحزم… +regexp_tooltip = تعامل مع عبارة البحث على أنها تعبير نمطي +commit_kind = البحث ضمن الإيداعات… +union = مطابقة عامة +runner_kind = البحث ضمن المشغِّلات… +exact = مطابق +exact_tooltip = عرض النتائج التي تطابق مصطلح البحث بالضبط فقط +regexp = RegExp +union_tooltip = عرض النتائج التي تطابق أي من الكلمات المفتاحية المفصولة بمسافات diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 8f4dfda0d1..84bb4ccde1 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -251,12 +251,12 @@ db_schema_helper=Leer lassen, um den Datenbank-Standardwert („public“) zu ve ssl_mode=SSL path=Pfad sqlite_helper=Dateipfad zur SQLite3-Datenbank.
Gib einen absoluten Pfad an, wenn Forgejo als Service gestartet wird. -reinstall_error=Du versuchst, in eine bereits existierende Forgejo Datenbank zu installieren +reinstall_error=Du versuchst, in eine bereits existierende Forgejo-Datenbank zu installieren reinstall_confirm_message=Eine Neuinstallation mit einer bestehenden Forgejo-Datenbank kann mehrere Probleme verursachen. In den meisten Fällen solltest du deine vorhandene „app.ini“ verwenden, um Forgejo auszuführen. Wenn du weißt, was du tust, bestätige die folgenden Angaben: reinstall_confirm_check_1=Die von der SECRET_KEY in app.ini verschlüsselten Daten können verloren gehen: Benutzer können sich unter Umständen nicht mit 2FA/OTP einloggen und Spiegel könnten nicht mehr richtig funktionieren. Mit der Ankreuzung dieses Kästchens bestätigst du, dass die aktuelle app.ini-Datei den korrekten SECRET_KEY enthält. reinstall_confirm_check_2=Die Repositorys und Einstellungen müssen eventuell neu synchronisiert werden. Durch das Ankreuzen dieses Kästchens bestätigst du, dass du die Hooks für die Repositorys und die authorized_keys-Datei manuell neu synchronisierst. Du bestätigst, dass du sicherstellst, dass die Repository- und Spiegeleinstellungen korrekt sind. reinstall_confirm_check_3=Du bestätigst, dass du absolut sicher bist, dass diese Forgejo mit der richtigen app.ini läuft, und du sicher bist, dass du neu installieren musst. Du bestätigst, dass du die oben genannten Risiken anerkennst. -err_empty_db_path=Der SQLite3 Datenbankpfad darf nicht leer sein. +err_empty_db_path=Der SQLite3-Datenbankpfad darf nicht leer sein. no_admin_and_disable_registration=Du kannst Selbst-Registrierungen nicht deaktivieren, ohne ein Administratorkonto zu erstellen. err_empty_admin_password=Das Administrator-Passwort darf nicht leer sein. err_empty_admin_email=Die Administrator-E-Mail darf nicht leer sein. @@ -463,7 +463,7 @@ openid_register_title=Neues Konto einrichten openid_register_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu. openid_signin_desc=Gib deine OpenID-URI ein, zum Beispiel alice.openid.example.org oder https://openid.example.org/alice. disable_forgot_password_mail=Die Kontowiederherstellung ist deaktiviert, da keine E-Mail eingerichtet ist. Bitte kontaktiere den zuständigen Administrator. -disable_forgot_password_mail_admin=Die Kontowiederherstellung ist nur verfügbar, wenn eine E-Mail eingerichtet wurde. Bitte richte eine E-Mail Adresse ein, um die Kontowiederherstellung freizuschalten. +disable_forgot_password_mail_admin=Die Kontowiederherstellung ist nur verfügbar, wenn eine E-Mail eingerichtet wurde. Bitte richte eine E-Mail-Adresse ein, um die Kontowiederherstellung freizuschalten. email_domain_blacklisted=Du kannst dich nicht mit deiner E-Mail-Adresse registrieren. authorize_application=Anwendung autorisieren authorize_redirect_notice=Du wirst zu %s weitergeleitet, wenn du diese Anwendung autorisierst. @@ -530,8 +530,8 @@ issue.action.merge=@%[1]s hat #%[2]d in %[3]s zusammengeführt. issue.action.approve=@%[1]s hat diesen Pull-Request genehmigt. issue.action.reject=@%[1]s hat Änderungen auf diesem Pull-Request angefordert. issue.action.review=@%[1]s hat diesen Pull-Request kommentiert. -issue.action.review_dismissed=@%[1]s hat das letzte Review von %[2]s für diesen Pull-Request verworfen. -issue.action.ready_for_review=@%[1]s hat diesen Pull-Request zum Review freigegeben. +issue.action.review_dismissed=@%[1]s hat die letzte Sichtung von %[2]s für diesen Pull-Request verworfen. +issue.action.ready_for_review=@%[1]s hat diesen Pull-Request für die Sichtung freigegeben. issue.action.new=@%[1]s hat #%[2]d geöffnet. issue.in_tree_path=In %s: @@ -540,8 +540,8 @@ release.new.text=@%[1]s hat %[2]s in %[3]s released release.title=Titel: %s release.note=Anmerkung: release.downloads=Downloads: -release.download.zip=Quellcode (ZIP Datei) -release.download.targz=Quellcode (TAR.GZ Datei) +release.download.zip=Quellcode (ZIP) +release.download.targz=Quellcode (TAR.GZ) repo.transfer.subject_to=%s möchte „%s“ an %s übertragen repo.transfer.subject_to_you=%s möchte dir „%s“ übertragen @@ -787,7 +787,7 @@ comment_type_group_time_tracking=Zeiterfassung comment_type_group_deadline=Frist comment_type_group_dependency=Abhängigkeit comment_type_group_lock=Sperrstatus -comment_type_group_review_request=Angeforderte Reviews +comment_type_group_review_request=Angeforderte Sichtungen comment_type_group_pull_request_push=Hinzugefügte Commits comment_type_group_project=Projekt comment_type_group_issue_ref=Issue-Referenz @@ -873,7 +873,7 @@ gpg_key_matched_identities_long=Die eingebetteten Identitäten in diesem Schlüs gpg_key_verified=Verifizierter Schlüssel gpg_key_verified_long=Der Schlüssel wurde mit einem Token verifiziert. Er kann verwendet werden, um Commits zu verifizieren, die mit irgendeiner für diesen Nutzer aktivierten E-Mail-Adresse und irgendeiner Identität dieses Schlüssels übereinstimmen. gpg_key_verify=Verifizieren -gpg_invalid_token_signature=Der GPG-Key, die Signatur, und das Token stimmen nicht überein, oder das Token ist veraltet. +gpg_invalid_token_signature=Der GPG-Key, die Signatur und das Token stimmen nicht überein, oder das Token ist veraltet. gpg_token_required=Du musst eine Signatur für das folgende Token angeben gpg_token=Token gpg_token_help=Du kannst eine Signatur wie folgt generieren: @@ -902,10 +902,10 @@ add_principal_success=Die SSH-Zertifikatsidentität „%s“ wurde hinzugefügt. delete_key=Entfernen ssh_key_deletion=SSH-Schlüssel entfernen gpg_key_deletion=GPG-Schlüssel entfernen -ssh_principal_deletion=SSH-Zertifik-Identität entfernen +ssh_principal_deletion=SSH-Zertifikats-Principal entfernen ssh_key_deletion_desc=Wenn du einen SSH-Key entfernst, hast du mit diesem Key keinen Zugriff mehr. Fortfahren? gpg_key_deletion_desc=Wenn du einen GPG-Schlüssel entfernst, können damit unterschriebene Commits nicht mehr verifiziert werden. Fortfahren? -ssh_principal_deletion_desc=Das Entfernen einer SSH-Zertifikat-Identität entzieht den Zugriff auf dein Konto. Fortfahren? +ssh_principal_deletion_desc=Das Entfernen eines SSH-Zertifikats-Principals entzieht den Zugriff auf dein Konto. Fortfahren? ssh_key_deletion_success=Der SSH-Schlüssel wurde entfernt. gpg_key_deletion_success=Der GPG-Schlüssel wurde entfernt. ssh_principal_deletion_success=Die Identität wurde entfernt. @@ -931,7 +931,7 @@ unbind_success=Das soziale Konto wurde erfolgreich entfernt. manage_access_token=Zugriffstokens generate_new_token=Neuen Token erzeugen -tokens_desc=Diese Tokens gewähren vollen Zugriff auf dein Konto via die Forgejo-API. +tokens_desc=Diese Tokens gewähren vollen Zugriff auf dein Konto mit der Forgejo-API. token_name=Token-Name generate_token=Token generieren generate_token_success=Ein neuer Token wurde generiert. Kopiere diesen jetzt, da er nicht erneut angezeigt wird. @@ -970,8 +970,8 @@ save_application=Speichern oauth2_client_id=Client-ID oauth2_client_secret=Client-Geheimnis oauth2_regenerate_secret=Geheimnis neu generieren -oauth2_regenerate_secret_hint=Secret verloren? -oauth2_client_secret_hint=Das Secret wird nach dem Verlassen oder Aktualisieren dieser Seite nicht mehr angezeigt. Bitte stelle sicher, dass du es gespeichert hast. +oauth2_regenerate_secret_hint=Geheimnis verloren? +oauth2_client_secret_hint=Das Geheimnis wird nach dem Verlassen oder Aktualisieren dieser Seite nicht mehr angezeigt. Bitte stelle sicher, dass du es gespeichert hast. oauth2_application_edit=Bearbeiten oauth2_application_create_description=OAuth2-Anwendungen geben deiner Drittanwendung Zugriff auf Benutzeraccounts dieser Forgejo-Instanz. oauth2_application_remove_description=Das Entfernen einer OAuth2-Anwendung hat zur Folge, dass diese nicht mehr auf autorisierte Benutzeraccounts auf dieser Instanz zugreifen kann. Möchtest Du fortfahren? @@ -996,11 +996,11 @@ twofa_disable_desc=Wenn du die Zwei-Faktor-Authentifizierung deaktivierst, wird regenerate_scratch_token_desc=Wenn du deinen Wiederherstellungsschlüssel verlegst oder es bereits benutzt hast, kannst du es hier zurücksetzen. twofa_disabled=Zwei-Faktor-Authentifizierung wurde deaktiviert. scan_this_image=Scanne diese Grafik mit deiner Authentifizierungs-App: -or_enter_secret=Oder gib das Secret ein: %s +or_enter_secret=Oder gib das Geheimnis ein: %s then_enter_passcode=Und gib dann die angezeigte PIN der Anwendung ein: passcode_invalid=Die PIN ist falsch. Probiere es erneut. twofa_enrolled=Die Zwei-Faktor-Authentifizierung wurde für dein Konto aktiviert. Bewahre deinen einmalig verwendbaren Wiederherstellungsschlüssel (%s) an einem sicheren Ort auf, da er nicht wieder angezeigt werden wird. -twofa_failed_get_secret=Fehler beim Abrufen des Secrets. +twofa_failed_get_secret=Fehler beim Abrufen des Geheimnisses. webauthn_desc=Sicherheitsschlüssel sind Geräte, die kryptografische Schlüssel beeinhalten. Diese können für die Zwei-Faktor-Authentifizierung verwendet werden. Der Sicherheitsschlüssel muss den Standard „WebAuthn“ unterstützen. webauthn_register_key=Sicherheitsschlüssel hinzufügen @@ -1185,9 +1185,9 @@ blame.ignore_revs=Revisionen in .git-blame-ignore-revs werden i blame.ignore_revs.failed=Fehler beim Ignorieren der Revisionen in .git-blame-ignore-revs. author_search_tooltip=Zeigt maximal 30 Benutzer -tree_path_not_found_commit=Pfad %[1]s existiert nicht in Commit%[2]s -tree_path_not_found_branch=Pfad %[1]s existiert nicht in Branch %[2]s -tree_path_not_found_tag=Pfad %[1]s existiert nicht in Tag %[2]s +tree_path_not_found_commit=Pfad %[1]s existiert nicht im Commit %[2]s +tree_path_not_found_branch=Pfad %[1]s existiert nicht im Branch %[2]s +tree_path_not_found_tag=Pfad %[1]s existiert nicht im Tag %[2]s transfer.accept=Übertragung akzeptieren transfer.accept_desc=Übertragung nach „%s“ @@ -1248,7 +1248,7 @@ migrate.clone_local_path=oder ein lokaler Serverpfad migrate.permission_denied=Du hast keine Berechtigung zum Importieren lokaler Repositorys. migrate.permission_denied_blocked=Du kannst von keinen nicht erlaubten Hosts importieren. Bitte fragen deinen Administrator, die Einstellungen ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS zu überprüfen. migrate.invalid_local_path=Der lokale Pfad ist ungültig. Er existiert nicht oder ist kein Verzeichnis. -migrate.invalid_lfs_endpoint=Ungültiger LFS Endpunkt. +migrate.invalid_lfs_endpoint=Der LFS-Endpunkt ist nicht gültig. migrate.failed=Fehler bei der Migration: %v migrate.migrate_items_options=Zugangs-Token wird benötigt, um zusätzliche Elemente zu migrieren migrated_from=Migriert von %[2]s @@ -1324,7 +1324,7 @@ commit=Commit release=Release releases=Releases tag=Tag -released_this=hat released +released_this=hat releast tagged_this=hat getaggt file.title=%s an %s file_raw=Originalformat @@ -1448,7 +1448,7 @@ commits.older=Älter commits.newer=Neuer commits.signed_by=Signiert von commits.signed_by_untrusted_user=Signiert von nicht vertrauenswürdigen Benutzern -commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdigen Benutzern, der nicht mit dem Committer übereinstimmt +commits.signed_by_untrusted_user_unmatched=Von einem nicht vertrauenswürdigen Benutzer, der nicht auf den Committer passt, signiert commits.gpg_key_id=GPG-Schlüssel-ID commits.ssh_key_fingerprint=SSH-Schlüssel-Fingerabdruck commits.view_path=An diesem Punkt im Verlauf anzeigen @@ -1459,7 +1459,7 @@ commit.revert-header=Setze zurück: %s commit.revert-content=Branch auswählen, der zurückgesetzt werden soll: commit.cherry-pick=Cherry-Pick commit.cherry-pick-header=Cherry-Picke: %s -commit.cherry-pick-content=Branch auswählen, auf dem Cherry-Picked werden soll: +commit.cherry-pick-content=Branch auswählen, zu dem das Ergebnis des Cherry-Picks angewendet werden soll: commitstatus.error=Fehler commitstatus.failure=Fehler @@ -1515,7 +1515,7 @@ issues.filter_assignees=Verantwortliche filtern issues.filter_milestones=Meilenstein filtern issues.filter_projects=Projekt filtern issues.filter_labels=Label filtern -issues.filter_reviewers=Reviewer filtern +issues.filter_reviewers=Sichter filtern issues.new=Neues Issue issues.new.title_empty=Der Titel kann nicht leer sein issues.new.labels=Labels @@ -1535,7 +1535,7 @@ issues.new.closed_milestone=Geschlossene Meilensteine issues.new.assignees=Zuständige issues.new.clear_assignees=Zuständige entfernen issues.new.no_assignees=Niemand zuständig -issues.new.no_reviewers=Keine Reviewer +issues.new.no_reviewers=Keine Sichter issues.choose.get_started=Los geht's issues.choose.open_external_link=Öffnen issues.choose.blank=Standard @@ -1598,8 +1598,8 @@ issues.filter_type.all_issues=Alle Issues issues.filter_type.assigned_to_you=Dir zugewiesen issues.filter_type.created_by_you=Von dir erstellt issues.filter_type.mentioning_you=Hat dich erwähnt -issues.filter_type.review_requested=Review angefordert -issues.filter_type.reviewed_by_you=Von dir gereviewt +issues.filter_type.review_requested=Sichtung angefordert +issues.filter_type.reviewed_by_you=Von dir gesichtet issues.filter_sort=Sortieren issues.filter_sort.latest=Neueste issues.filter_sort.oldest=Älteste @@ -1621,8 +1621,8 @@ issues.action_milestone=Meilenstein issues.action_milestone_no_select=Kein Meilenstein issues.action_assignee=Zuständig issues.action_assignee_no_select=Niemand zuständig -issues.action_check=Auswählen/Auswahl aufheben -issues.action_check_all=Alles auswählen/Auswahl aufheben +issues.action_check=Auswählen / Auswahl aufheben +issues.action_check_all=Alles auswählen / Auswahl aufheben issues.opened_by=%[1]s von %[3]s geöffnet pulls.merged_by=von %[3]s wurde %[1]s zusammengeführt pulls.merged_by_fake=von %[2]s %[1]s zusammengeführt @@ -1673,12 +1673,12 @@ issues.role.first_time_contributor=Erstmaliger Mitwirkender issues.role.first_time_contributor_helper=Dies ist der erste Beitrag dieses Benutzers zum Repository. issues.role.contributor=Mitwirkender issues.role.contributor_helper=Dieser Benutzer hat schon zuvor zu dem Repository beigetragen. -issues.re_request_review=Review erneut anfordern -issues.is_stale=Seit diesem Review gab es Änderungen an diesem PR -issues.remove_request_review=Review-Anfrage entfernen -issues.remove_request_review_block=Review-Anfrage kann nicht entfernt werden -issues.dismiss_review=Review verwerfen -issues.dismiss_review_warning=Bist du dir sicher, dass du dieses Review verwerfen willst? +issues.re_request_review=Sichtung erneut anfordern +issues.is_stale=Seit dieser Sichtung gab es Änderungen an diesem PR +issues.remove_request_review=Sichtungsanfrage entfernen +issues.remove_request_review_block=Sichtungsanfrage kann nicht entfernt werden +issues.dismiss_review=Sichtung verwerfen +issues.dismiss_review_warning=Bist du dir sicher, dass du diese Sichtung verwerfen willst? issues.sign_in_require_desc=Anmelden, um an der Diskussion teilzunehmen. issues.edit=Bearbeiten issues.cancel=Abbrechen @@ -1809,20 +1809,20 @@ issues.dependency.add_error_dep_not_same_repo=Beide Issues müssen sich im selbe issues.review.self.approval=Du kannst nicht dein eigenen Pull-Request genehmigen. issues.review.self.rejection=Du kannst keine Änderungen an deinem eigenen Pull-Request anfragen. issues.review.approve=hat die Änderungen %s genehmigt -issues.review.comment=hat %s gereviewt +issues.review.comment=hat %s gesichtet issues.review.dismissed=verwarf %ss Review %s issues.review.dismissed_label=Verworfen issues.review.left_comment=hat einen Kommentar hinterlassen issues.review.content.empty=Du musst einen Kommentar hinterlassen, der die gewünschte(n) Änderung(en) beschreibt. issues.review.reject=hat %s Änderungen angefragt -issues.review.wait=wurde für ein Review %s angefragt -issues.review.add_review_request=hat ein Review von %[1]s %[2]s angefragt -issues.review.remove_review_request=hat die Aufforderung zum Review an %[1]s %[2]s entfernt -issues.review.remove_review_request_self=hat das Review verweigert %s +issues.review.wait=wurde für eine Sichtung von %s angefragt +issues.review.add_review_request=hat eine Sichtung von %[1]s %[2]s angefragt +issues.review.remove_review_request=hat die Sichtungsanfrage an %[1]s %[2]s entfernt +issues.review.remove_review_request_self=hat die Sichtung %s verweigert issues.review.pending=Ausstehend issues.review.pending.tooltip=Dieser Kommentar ist derzeit nicht für andere Benutzer sichtbar. Um deine ausstehenden Kommentare einzureichen, wähle „%s“ -> „%s/%s/%s“ oben auf der Seite. issues.review.review=Review -issues.review.reviewers=Reviewer +issues.review.reviewers=Sichter issues.review.outdated=Veraltet issues.review.outdated_description=Der Inhalt hat sich geändert, seit dieser Kommentar abgegeben wurde issues.review.option.show_outdated_comments=Veraltete Kommentare anzeigen @@ -1833,7 +1833,7 @@ issues.review.show_resolved=Erledigte anzeigen issues.review.hide_resolved=Erledigte ausblenden issues.review.resolve_conversation=Diskussion als „erledigt“ markieren issues.review.un_resolve_conversation=Diskussion als „nicht erledigt“ markieren -issues.review.resolved_by=markierte diese Unterhaltung als gelöst +issues.review.resolved_by=markierte diese Unterhaltung als „erledigt“ issues.assignee.error=Aufgrund eines unerwarteten Fehlers konnten nicht alle Zuständigen hinzugefügt werden. issues.reference_issue.body=Beschreibung issues.content_history.deleted=gelöscht @@ -1847,7 +1847,7 @@ issues.reference_link=Referenz: %s compare.compare_base=Basis compare.compare_head=vergleichen -pulls.desc=Pull-Requests und Code-Reviews aktivieren. +pulls.desc=Pull-Requests und Code-Sichtungen aktivieren. pulls.new=Neuer Pull-Request pulls.view=Pull-Request ansehen pulls.compare_changes=Neuer Pull-Request @@ -1856,7 +1856,7 @@ pulls.allow_edits_from_maintainers_desc=Nutzer mit Schreibzugriff auf den Basisb pulls.allow_edits_from_maintainers_err=Aktualisieren fehlgeschlagen pulls.compare_changes_desc=Wähle den Zielbranch, in das zusammengeführt werden soll, und den Quellbranch, von dem gepullt werden soll, aus. pulls.has_viewed_file=Gesehen -pulls.has_changed_since_last_review=Seit deinem letzten Review geändert +pulls.has_changed_since_last_review=Seit deiner letzten Sichtung geändert pulls.viewed_files_label=%[1]d / %[2]d Dateien betrachtet pulls.expand_files=Alle Dateien ausklappen pulls.collapse_files=Alle Dateien einklappen @@ -1867,11 +1867,11 @@ pulls.switch_head_and_base=Head und Base vertauschen pulls.filter_branch=Branch filtern pulls.no_results=Keine Ergebnisse verfügbar. pulls.show_all_commits=Alle Commits anzeigen -pulls.show_changes_since_your_last_review=Zeige Änderungen seit deinem letzten Review +pulls.show_changes_since_your_last_review=Zeige Änderungen seit deiner letzten Sichtung pulls.showing_only_single_commit=Nur Änderungen aus Commit %[1]s werden angezeigt pulls.showing_specified_commit_range=Zeige nur die Änderungen zwischen %[1]s..%[2]s pulls.select_commit_hold_shift_for_range=Commit auswählen. Halte Shift + klicke, um eine Reihe auszuwählen -pulls.review_only_possible_for_full_diff=Ein Review ist nur möglich, wenn das vollständige Diff angezeigt wird +pulls.review_only_possible_for_full_diff=Eine Sichtung ist nur möglich, wenn der vollständige Diff angezeigt wird pulls.filter_changes_by_commit=Nach Commit filtern pulls.nothing_to_compare=Diese Branches sind identisch. Es muss kein Pull-Request erstellt werden. pulls.nothing_to_compare_and_allow_empty_pr=Diese Branches sind gleich. Der Pull-Request wird leer sein. @@ -1905,8 +1905,8 @@ pulls.required_status_check_failed=Einige erforderliche Prüfungen waren nicht e pulls.required_status_check_missing=Einige erforderliche Prüfungen fehlen. pulls.required_status_check_administrator=Als Administrator kannst du diesen Pull-Request weiterhin zusammenführen. pulls.blocked_by_approvals=Dieser Pull-Request hat noch nicht genügend Genehmigungen. %d von %d Genehmigungen erteilt. -pulls.blocked_by_rejection=Dieser Pull-Request hat Änderungen, die von einem offiziellen Reviewer angefragt wurden. -pulls.blocked_by_official_review_requests=Dieser Pull-Request ist blockiert, weil ihm die Genehmigung von einem oder mehreren offiziellen Reviewern fehlt. +pulls.blocked_by_rejection=Dieser Pull-Request hat Änderungen, die von einem offiziellen Sichter angefragt wurden. +pulls.blocked_by_official_review_requests=Dieser Pull-Request ist blockiert, weil ihm die Genehmigung von einem oder mehreren offiziellen Sichtern fehlt. pulls.blocked_by_outdated_branch=Dieser Pull-Request ist blockiert, da er veraltet ist. pulls.blocked_by_changed_protected_files_1=Dieser Pull-Request ist blockiert, weil er eine geschützte Datei ändert: pulls.blocked_by_changed_protected_files_n=Dieser Pull-Request ist blockiert, weil er geschützte Dateien ändert: @@ -1919,14 +1919,14 @@ pulls.approve_count_1=%d Genehmigung pulls.approve_count_n=%d Genehmigungen pulls.reject_count_1=%d Änderungsanfrage pulls.reject_count_n=%d Änderungsanfragen -pulls.waiting_count_1=%d wartendes Review -pulls.waiting_count_n=%d wartende Reviews +pulls.waiting_count_1=%d wartende Sichtung +pulls.waiting_count_n=%d wartende Sichtungen pulls.wrong_commit_id=die Commit-ID muss eine Commit-ID auf dem Zielbranch sein pulls.no_merge_desc=Dieser Pull-Request kann nicht zusammengeführt werden, da alle Repository-Merge-Optionen deaktiviert sind. pulls.no_merge_helper=Aktiviere Mergeoptionen in den Repositoryeinstellungen oder führe den Pull-Request manuell zusammen. pulls.no_merge_wip=Dieser Pull-Request kann nicht zusammengeführt werden, da er als „Work in Progress“ (in Bearbeitung) markiert ist. -pulls.no_merge_not_ready=Dieser Pull-Request kann nicht zusammengeführt werden, überprüfe den Reviewstatus und die Statusprüfungen. +pulls.no_merge_not_ready=Dieser Pull-Request kann nicht zusammengeführt werden, überprüfe den Sichtungsstatus und die Statusprüfungen. pulls.no_merge_access=Du bist nicht berechtigt, diesen Pull-Request zusammenzuführen. pulls.merge_pull_request=Merge-Commit erstellen pulls.rebase_merge_pull_request=Rebasen und dann fast-forwarden @@ -2202,7 +2202,7 @@ settings.tracker_issue_style.numeric=Numerisch settings.tracker_issue_style.alphanumeric=Alphanumerisch settings.tracker_issue_style.regexp=Regulärer Ausdruck settings.tracker_issue_style.regexp_pattern=Regulärer Ausdruck -settings.tracker_issue_style.regexp_pattern_desc=Die erste gecapturte Gruppe wird statt {index} verwendet. +settings.tracker_issue_style.regexp_pattern_desc=Die erste gefundene Gruppe wird statt {index} verwendet. settings.tracker_url_format_desc=Du kannst die Platzhalter {user}, {repo}, {index} für den Benutzernamen, den Namen des Repositorys und die Issue-Nummer verwenden. settings.enable_timetracker=Zeiterfassung aktivieren settings.allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen @@ -2261,14 +2261,14 @@ settings.trust_model.collaborator=Mitarbeiter settings.trust_model.collaborator.long=Mitarbeiter: Vertraue Signaturen von Mitarbeitern settings.trust_model.collaborator.desc=Gültige Signaturen von Mitarbeitern dieses Projekts werden als „vertrauenswürdig“ markiert (egal, ob sie mit dem Committer übereinstimmen oder nicht). Andernfalls werden gültige Signaturen als „nicht vertrauenswürdig“ markiert, falls die Signatur zum Committer passt, ansonsten werden sie als „nicht übereinstimmend“ markiert. settings.trust_model.committer=Committer -settings.trust_model.committer.long=Committer: Vertraue Signaturen, die zu Committern passen (Dies stimmt mit GitHub überein und zwingt signierte Commits von Forgejo dazu, Forgejo als Committer zu haben) +settings.trust_model.committer.long=Committer: Vertraue Signaturen, die zu Committern passen (dies stimmt mit GitHub überein und zwingt signierte Commits von Forgejo dazu, Forgejo als Committer zu haben) settings.trust_model.committer.desc=Gültige Signaturen werden nur dann als „vertrauenswürdig“ gekennzeichnet, wenn sie mit ihrem Committer übereinstimmen. Ansonsten werden sie als „nicht übereinstimmend“ markiert. Das führt dazu, dass Forgejo auf signierten Commits, bei denen der echte Committer als „Co-authored-by:“ oder „Co-committed-by:“ in der Beschreibung eingetragen wurde, als Committer gilt. Der Forgejo-Standard-Key muss zu einem Benutzer in der Datenbank passen. settings.trust_model.collaboratorcommitter=Mitarbeiter+Committer settings.trust_model.collaboratorcommitter.long=Mitarbeiter+Committer: Signaturen der Mitarbeiter vertrauen die mit dem Committer übereinstimmen settings.trust_model.collaboratorcommitter.desc=Gültige Signaturen von Mitarbeitern dieses Projekts werden als „vertrauenswürdig“ markiert, wenn sie mit dem Committer übereinstimmen. Andernfalls werden gültige Signaturen als „nicht vertrauenswürdig“ markiert, wenn die Signatur mit dem Committer übereinstimmt. Ansonsten werden sie als „nicht übereinstimmend“ markiert. Dies zwingt Forgejo, als Committer bei signierten Commits mit dem echten Committer als „Co-Authored-By:“ und „Co-Committed-By:“ im Commit zu markieren. Der Standard-Forgejo-Schlüssel muss mit einem Benutzer in der Datenbank übereinstimmen. settings.wiki_delete=Wiki-Daten löschen settings.wiki_delete_desc=Das Löschen von Wiki-Daten kann nicht rückgängig gemacht werden. Bitte sei vorsichtig. -settings.wiki_delete_notices_1=– Dies löscht und deaktiviert das Wiki für %s. +settings.wiki_delete_notices_1=– Dies wird das Repository-Wiki für %s dauerhaft löschen und deaktivieren. settings.confirm_wiki_delete=Wiki-Daten löschen settings.wiki_deletion_success=Repository-Wiki-Daten wurden gelöscht. settings.delete=Dieses Repository löschen @@ -2327,7 +2327,7 @@ settings.add_webhook_desc=Forgejo sendet eine POST-Anfrage mit fest settings.payload_url=Ziel-URL settings.http_method=HTTP-Methode settings.content_type=POST-Content-Type -settings.secret=Secret +settings.secret=Geheimnis settings.slack_username=Benutzername settings.slack_icon_url=Icon-URL settings.slack_color=Farbe @@ -2374,12 +2374,12 @@ settings.event_pull_request_milestone=Meilensteine settings.event_pull_request_milestone_desc=Meilenstein hinzugefügt, entfernt oder bearbeitet. settings.event_pull_request_comment=Kommentare settings.event_pull_request_comment_desc=Pull-Request-Kommentar angelegt, geändert oder gelöscht. -settings.event_pull_request_review=Reviews -settings.event_pull_request_review_desc=Pull-Request genehmigt, abgelehnt oder Review-Kommentare hinterlassen. +settings.event_pull_request_review=Sichtungen +settings.event_pull_request_review_desc=Pull-Request genehmigt, abgelehnt oder Sichtungskommentare hinterlassen. settings.event_pull_request_sync=Synchronisiert settings.event_pull_request_sync_desc=Branch automatisch mit Zielbranch aktualisiert. -settings.event_pull_request_review_request=Review-Anfragen -settings.event_pull_request_review_request_desc=Überprüfung des Pull-Requests angefragt oder die Anfrage entfernt. +settings.event_pull_request_review_request=Sichtungsanfragen +settings.event_pull_request_review_request_desc=Pull-Request-Sichtung angefragt oder Sichtungsanfrage entfernt. settings.event_pull_request_approvals=Genehmigungen zum Pull-Request settings.event_pull_request_merge=Pull-Request-Merge settings.event_package=Paket @@ -2467,11 +2467,11 @@ settings.protect_status_check_matched=Übereinstimmung settings.protect_invalid_status_check_pattern=Ungültiges Statusprüfungspattern: „%s“. settings.protect_no_valid_status_check_patterns=Keine gültigen Statuscheck-Muster. settings.protect_required_approvals=Erforderliche Genehmigungen -settings.protect_required_approvals_desc=Erlaube das Zusammenführen des Pull-Requests nur mit genügend positiven Reviews. +settings.protect_required_approvals_desc=Erlaube das Zusammenführen des Pull-Requests nur mit genügend positiven Sichtungen. settings.protect_approvals_whitelist_enabled=Genehmigungen auf Benutzer oder Teams auf der Positivliste beschränken -settings.protect_approvals_whitelist_enabled_desc=Nur Reviews von Benutzern oder Teams auf der Positivliste zählen zu den erforderlichen Genehmigungen. Existiert keine Positivliste, so zählen Reviews von jedem mit Schreibzugriff zu den erforderlichen Genehmigungen. -settings.protect_approvals_whitelist_users=Nutzer, die reviewen dürfen -settings.protect_approvals_whitelist_teams=Teams, die reviewen dürfen +settings.protect_approvals_whitelist_enabled_desc=Nur Sichtungen von Benutzern oder Teams auf der Positivliste zählen zu den erforderlichen Genehmigungen. Existiert keine Positivliste, so zählen Sichtungen von jedem mit Schreibzugriff zu den erforderlichen Genehmigungen. +settings.protect_approvals_whitelist_users=Nutzer, die sichten dürfen +settings.protect_approvals_whitelist_teams=Teams, die sichten dürfen settings.dismiss_stale_approvals=Entferne alte Genehmigungen settings.dismiss_stale_approvals_desc=Wenn neue Commits gepusht werden, die den Inhalt des Pull-Requests ändern, werden alte Genehmigungen entfernt. settings.require_signed_commits=Signierte Commits erforderlich @@ -2489,10 +2489,10 @@ settings.remove_protected_branch_success=Branchschutzregel „%s“ wurde entfer settings.remove_protected_branch_failed=Entfernen der Branchschutzregel „%s“ fehlgeschlagen. settings.protected_branch_deletion=Branch-Schutz löschen settings.protected_branch_deletion_desc=Wenn du den Branch-Schutz deaktivierst, können alle Nutzer mit Schreibrechten auf den Branch pushen. Fortfahren? -settings.block_rejected_reviews=Zusammenführung bei abgelehnten Reviews blockieren -settings.block_rejected_reviews_desc=Merge ist nicht möglich, wenn Änderungen durch offizielle Reviewer angefragt werden, auch wenn genügend Genehmigungen existieren. -settings.block_on_official_review_requests=Merge bei offiziellen Review-Anfragen blockieren -settings.block_on_official_review_requests_desc=Merge ist nicht möglich, wenn offizielle Review-Anfrangen vorliegen, selbst wenn genügend Genehmigungen existieren. +settings.block_rejected_reviews=Zusammenführung bei abgelehnten Sichtungen blockieren +settings.block_rejected_reviews_desc=Merge ist nicht möglich, wenn Änderungen durch offizielle Sichter angefragt werden, auch wenn genügend Genehmigungen existieren. +settings.block_on_official_review_requests=Merge bei offiziellen Sichtungsanfragen blockieren +settings.block_on_official_review_requests_desc=Merge ist nicht möglich, wenn offizielle Sichtungsanfrangen vorliegen, selbst wenn genügend Genehmigungen existieren. settings.block_outdated_branch=Merge blockieren, wenn der Pull-Request veraltet ist settings.block_outdated_branch_desc=Merge ist nicht möglich, wenn der Head-Branch hinter dem Basis-Branch ist. settings.default_branch_desc=Wähle einen Standardbranch für Pull-Requests und Code-Commits: @@ -2539,7 +2539,7 @@ settings.lfs_filelist=LFS-Dateien, die in diesem Repository gespeichert sind settings.lfs_no_lfs_files=In diesem Repository sind keine LFS-Dateien gespeichert settings.lfs_findcommits=Commits finden settings.lfs_lfs_file_no_commits=Keine Commits für diese LFS-Datei gefunden -settings.lfs_noattribute=Dieser Pfad hat nicht das sperrbare Attribut im Standard-Branch +settings.lfs_noattribute=Dieser Pfad hat nicht das „lockable“-Attribut im Standard-Branch settings.lfs_delete=LFS-Datei mit OID %s löschen settings.lfs_delete_warning=Das Löschen einer LFS-Datei kann dazu führen, dass „Objekt existiert nicht“-Fehler beim Checkout auftreten. Bist du sicher? settings.lfs_findpointerfiles=Pointer-Dateien finden @@ -2580,8 +2580,8 @@ diff.show_unified_view=Gesamtansicht diff.whitespace_button=Leerzeichen diff.whitespace_show_everything=Alle Änderungen anzeigen diff.whitespace_ignore_all_whitespace=Ignoriere Leerzeichen beim Zeilen vergleichen -diff.whitespace_ignore_amount_changes=Ignoriere whitespace-Änderungen -diff.whitespace_ignore_at_eol=Ignoriere EOL-whitespace-Änderungen +diff.whitespace_ignore_amount_changes=Änderungen in der Anzahl der Leerzeichen und ähnlichen Zeichen ignorieren +diff.whitespace_ignore_at_eol=Änderungen an den Leerzeichen und ähnlichen Zeichen am Zeilenende ignorieren diff.stats_desc= %d geänderte Dateien mit %d neuen und %d gelöschten Zeilen diff.stats_desc_file=%d Änderungen: %d Ergänzungen und %d Löschungen diff.bin=BIN @@ -2604,11 +2604,11 @@ diff.comment.placeholder=Kommentieren diff.comment.markdown_info=Styling mit Markdown wird unterstützt. diff.comment.add_single_comment=Einzelnen Kommentar hinzufügen diff.comment.add_review_comment=Kommentar hinzufügen -diff.comment.start_review=Review starten +diff.comment.start_review=Sichtung starten diff.comment.reply=Antworten -diff.review=Review abschließen -diff.review.header=Review einreichen -diff.review.placeholder=Kommentar zum Review +diff.review=Sichtung abschließen +diff.review.header=Sichtung einreichen +diff.review.placeholder=Kommentar zur Sichtung diff.review.comment=Kommentieren diff.review.approve=Genehmigen diff.review.self_reject=Pull-Request-Autoren können keine Änderungen an ihren eigenen Pull-Request anfordern @@ -2656,7 +2656,7 @@ release.edit_release=Release aktualisieren release.delete_release=Release löschen release.delete_tag=Tag löschen release.deletion=Release löschen -release.deletion_desc=Beim Entfernen wird ein Release nur von Forgejo gelöscht. Es betrifft weder den Git-Tag, noch den Inhalt des Repos oder seinen Änderungsverlauf. Fortfahren? +release.deletion_desc=Beim Entfernen wird ein Release nur von Forgejo gelöscht. Es betrifft weder den Git-Tag noch den Inhalt des Repos oder seinen Änderungsverlauf. Fortfahren? release.deletion_success=Das Release wurde gelöscht. release.deletion_tag_desc=Löscht dieses Tag aus dem Projektarchiv. Repository-Inhalt und Verlauf bleiben unverändert. Fortfahren? release.deletion_tag_success=Der Tag wurde gelöscht. @@ -2666,7 +2666,7 @@ release.tag_name_protected=Der Tag-Name ist geschützt. release.tag_already_exist=Dieser Tag-Name existiert bereits. release.downloads=Downloads release.download_count=Downloads: %s -release.add_tag_msg=Titel und Beschreibung des Releases als Tag Nachricht verwenden. +release.add_tag_msg=Titel und Beschreibung des Releases als Tag-Nachricht verwenden. release.add_tag=Tag erstellen release.releases_for=Releases für %s release.tags_for=Tags für %s @@ -2766,7 +2766,7 @@ wiki.cancel = Abbrechen settings.wiki_globally_editable = Allen erlauben, das Wiki zu bearbeiten settings.protect_branch_name_pattern_desc = Geschützte Branch-Namens-Patterns. Siehe die Dokumentation für Pattern-Syntax. Beispiele: main, release/** settings.ignore_stale_approvals = Abgestandene Genehmigungen ignorieren -settings.ignore_stale_approvals_desc = Genehmigungen, welche für ältere Commits gemacht wurden (abgestandene Reviews), nicht in die Gesamtzahl der Genehmigung des PRs mitzählen. Irrelevant, falls abgestandene Reviews bereits verworfen werden. +settings.ignore_stale_approvals_desc = Genehmigungen, welche für ältere Commits gemacht wurden (abgestandene Sichtungen), nicht in die Gesamtzahl der Genehmigung des PRs mitzählen. Irrelevant, falls abgestandene Sichtungen bereits verworfen werden. pulls.commit_ref_at = `referenzierte diesen Pull-Request aus einem Commit %s` pulls.fast_forward_only_merge_pull_request = Nur Fast-forward pulls.cmd_instruction_checkout_desc = Checke einen neuen Branch aus deinem Projekt-Repository aus und teste die Änderungen. @@ -2782,7 +2782,7 @@ activity.navbar.contributors = Mitwirkende contributors.contribution_type.deletions = Löschungen contributors.contribution_type.additions = Einfügungen contributors.contribution_type.filter_label = Art des Beitrags: -vendored = Vendored +vendored = Gevendort activity.navbar.pulse = Puls pulls.made_using_agit = AGit settings.confirmation_string = Bestätigungsstring @@ -2795,7 +2795,7 @@ pulls.merged_title_desc_one = hat %[1]d Commit von %[2]s nach %[2]s nach %[3]s zusammenführen open_with_editor = Öffnen mit %s commits.search_branch = Dieser Branch -pulls.ready_for_review = Bereit zum Review? +pulls.ready_for_review = Bereit zur Sichtung? settings.rename_branch_failed_protected = Branch %s kann nicht umbenannt werden, weil er ein geschützter Branch ist. editor.commit_id_not_matching = Die Datei wurde geändert, während du sie bearbeitet hast. Committe in einen neuen Branch, dann führe einen Merge durch. editor.push_out_of_date = Der Push scheint veraltet zu sein. @@ -2824,7 +2824,7 @@ settings.sourcehut_builds.secrets_helper = Dem Job zugriff auf die Build-Geheimn settings.web_hook_name_sourcehut_builds = SourceHut-Builds settings.graphql_url = GraphQL-URL settings.matrix.room_id_helper = Die Raum-ID kann über den Element-Webclient ermittelt werden: Raumeinstellungen > erweitert > interne Raum-ID. Beispielsweise %s. -settings.sourcehut_builds.access_token_helper = Zugangstoken, der die JOBS:RW-Freigabe hat. Generiere auf meta.sr.ht einen builds.sr.ht-Token oder einen builds.sr.ht-Token mit Zugriff auf die Secrets. +settings.sourcehut_builds.access_token_helper = Zugangstoken, der die JOBS:RW-Freigabe hat. Generiere auf meta.sr.ht einen builds.sr.ht-Token oder einen builds.sr.ht-Token mit Zugriff auf die Geheimnisse. settings.matrix.access_token_helper = Es wird empfohlen, hierfür ein dediziertes Matrix-Konto anzulegen. Der Zugangstoken kann in einem Inkognito-Tab über den Element-Webclient geholt werden: Benutzermenü (oben links) > alle Einstellungen > Hilfe & Info > erweitert > Zugriffstoken (direkt unter der Heim-Server-URL). Schließe dann den Inkognito-Tab (Abmelden würde den Token ungültig machen). release.hide_archive_links = Automatisch generierte Archive verstecken release.hide_archive_links_helper = Verstecke automatisch generierte Quellcodearchive für diesen Release. Zum Beispiel, wenn du deine eigenen hochlädst. @@ -2873,9 +2873,9 @@ mirror_use_ssh.not_available = SSH-Authentifizierung ist nicht verfügbar. issues.new.assign_to_me = Mir selbst zuweisen issues.all_title = Alle settings.discord_icon_url.exceeds_max_length = Die Icon-URL darf eine Länge von 2048 Zeichen nicht überschreiten -issues.review.add_review_requests = hat Reviews von %[1]s %[2]s angefragt -issues.review.remove_review_requests = hat Aufforderungen zum Review an %[1]s %[2]s entfernt -issues.review.add_remove_review_requests = hat Reviews von %[1]s angefragt und hat die Aufforderungen zum Review an %[2]s %[3]s entfernt +issues.review.add_review_requests = hat Sichtungen von %[1]s %[2]s angefragt +issues.review.remove_review_requests = hat die Sichtungsanfragen an %[1]s %[2]s entfernt +issues.review.add_remove_review_requests = hat Sichtungen von %[1]s angefragt und die Sichtungsanfragen an %[2]s %[3]s entfernt pulls.delete_after_merge.head_branch.is_default = Der Head-Branch, den du löschen willst, ist der Standardbranch und kann nicht gelöscht werden. pulls.delete_after_merge.head_branch.is_protected = Der Head-Branch, den du löschen willst, ist ein geschützter Branch und kann nicht gelöscht werden. pulls.delete_after_merge.head_branch.insufficient_branch = Du hast keine Erlaubnis, den Head-Branch zu löschen. @@ -2883,9 +2883,9 @@ issues.filter_sort.relevance = Relevanz diff.git-notes.add = Anmerkung hinzufügen diff.git-notes.remove-header = Anmerkung entfernen diff.git-notes.remove-body = Diese Anmerkung wird entfernt. -issues.num_reviews_one = %d Review +issues.num_reviews_one = %d Sichtung issues.summary_card_alt = Zusammenfassung eines Issues mit dem Titel „%s“ im Repository %s -issues.num_reviews_few = %d Reviews +issues.num_reviews_few = %d Sichtungen editor.add_tmpl.filename = Dateiname settings.default_update_style_desc = Standard-Aktualisierungsart um Pull-Requests zu aktualisieren, die hinter dem Base-Branch sind. new_advanced = Erweiterte Einstellungen @@ -2902,7 +2902,7 @@ issues.reaction.alt_add = Füge %[1]s Reaktion zum Kommentar hinzu. issues.reaction.alt_remove = Entferne %[1]s Reaktion von diesem Kommentar. summary_card_alt = Zusammenfassungskarte des Repositorys %s release.summary_card_alt = Übersichtskarte eines Releases mit dem Titel „%s“ im Repository %s -archive.pull.noreview = Dieses Repository ist archiviert. Pull-Requests können nicht gereviewt werden. +archive.pull.noreview = Dieses Repository ist archiviert. Pull-Requests können nicht gesichtet werden. editor.commit_email = Commit-E-Mail commits.view_single_diff = Änderungen an dieser Datei, die in diesem Commit eingeführt wurden, betrachten pulls.editable = Bearbeitbar @@ -2922,7 +2922,7 @@ settings.event_action_success_desc = Action-Run war erfolgreich. settings.event_action_failure = Fehlschlag settings.event_action_success = Erfolg settings.event_header_action = Action-Run-Ereignisse -settings.event_action_recover_desc = Action-Run war erfolgreich, nachdem der letzte Action-Run im selben Arbeitsablauf fehlgeschlagen ist. +settings.event_action_recover_desc = Action-Run war erfolgreich, nachdem der letzte Action-Run im selben Workflow fehlgeschlagen ist. settings.event_action_recover = Wiederherstellen issues.filter_type.all_pull_requests = Alle Pull-Requests @@ -3116,7 +3116,7 @@ dashboard.repo_health_check=Healthchecks für alle Repositorys ausführen dashboard.check_repo_stats=Überprüfe alle Repository-Statistiken dashboard.archive_cleanup=Alte Repository-Archive löschen dashboard.deleted_branches_cleanup=Gelöschte Branches bereinigen -dashboard.update_migration_poster_id=Migration Poster-IDs updaten +dashboard.update_migration_poster_id=Migrations-Poster-IDs aktualisieren dashboard.git_gc_repos=Garbage-Collection für alle Repositorys ausführen dashboard.resync_all_sshkeys=Die Datei „.ssh/authorized_keys“ mit Forgejo-SSH-Schlüsseln aktualisieren. dashboard.resync_all_sshprincipals=Aktualisiere die Datei „.ssh/authorized_principals“ mit Forgejo-SSH-Principals. @@ -3159,7 +3159,7 @@ dashboard.delete_old_actions=Alle alten Aktivitäten aus der Datenbank löschen dashboard.delete_old_actions.started=Löschen aller alten Aktivitäten aus der Datenbank gestartet. dashboard.update_checker=Update-Checker dashboard.delete_old_system_notices=Alle alten Systemmeldungen aus der Datenbank löschen -dashboard.gc_lfs=Garbage-Collection für LFS Meta-Objekte ausführen +dashboard.gc_lfs=Garbage-Collection für LFS-Meta-Objekte ausführen dashboard.stop_zombie_tasks=Zombie-Actions-Aufgaben stoppen dashboard.stop_endless_tasks=Endlose Actions-Aufgaben stoppen dashboard.cancel_abandoned_jobs=Aufgegebene Actions-Jobs abbrechen @@ -3335,7 +3335,7 @@ auths.pam_email_domain=PAM-E-Mail-Domain (optional) auths.oauth2_provider=OAuth2-Anbieter auths.oauth2_icon_url=Symbol-URL auths.oauth2_clientID=Client-ID (Schlüssel) -auths.oauth2_clientSecret=Client-Secret +auths.oauth2_clientSecret=Client-Geheimnis auths.openIdConnectAutoDiscoveryURL=OpenID-Connect-Auto-Discovery-URL auths.oauth2_use_custom_url=Benutzerdefinierte URLs anstelle von Standard-URLs verwenden auths.oauth2_tokenURL=Token-URL @@ -3343,14 +3343,14 @@ auths.oauth2_authURL=Authorisierungs-URL auths.oauth2_profileURL=Profil-URL auths.oauth2_emailURL=E-Mail-URL auths.skip_local_two_fa=Lokale 2FA überspringen -auths.skip_local_two_fa_helper=Leer lassen bedeutet, dass lokale User die 2FA immer noch bestehen müssen, um sich anzumelden +auths.skip_local_two_fa_helper=Das Leerlassen bedeutet, dass lokale User die 2FA immer noch bestehen müssen, um sich anzumelden auths.oauth2_tenant=Inhaber auths.oauth2_scopes=Zusätzliche Bereiche auths.oauth2_required_claim_name=Benötigter Claim-Name auths.oauth2_required_claim_name_helper=Setze diesen Namen, damit Nutzer aus dieser Quelle sich nur anmelden dürfen, wenn sie einen Claim mit diesem Namen besitzen auths.oauth2_required_claim_value=Benötigter Claim-Wert auths.oauth2_required_claim_value_helper=Setze diesen Wert, damit Nutzer aus dieser Quelle sich nur anmelden dürfen, wenn sie einen Claim mit diesem Namen und Wert besitzen -auths.oauth2_group_claim_name=Claim-Name, der Gruppennamen für diese Quelle angibt. (Optional) +auths.oauth2_group_claim_name=Claim-Name, der Gruppennamen für diese Quelle angibt (optional). auths.oauth2_admin_group=Gruppen-Claim-Wert für Administratoren (optional – erfordert Claim-Namen oben). auths.oauth2_restricted_group=Gruppen-Claim-Wert für eingeschränkte User. (Optional – erfordert Claim-Namen oben) auths.oauth2_map_group_to_team=Gruppen aus OAuth-Claims den Organisationsteams zuordnen (optional – oben muss der Name des Claims angegeben werden). @@ -3395,7 +3395,7 @@ auths.still_in_used=Diese Authentifizierungsquelle wird noch verwendet. Bearbeit auths.deletion_success=Die Authentifizierungsquelle „%s“ wurde gelöscht. auths.login_source_exist=Die Authentifizierungsquelle „%s“ existiert bereits. auths.login_source_of_type_exist=Eine Authentifizierungart dieses Typs existiert bereits. -auths.unable_to_initialize_openid=OpenID Connect Provider konnte nicht initialisiert werden: %s +auths.unable_to_initialize_openid=Provider für OpenID Connect konnte nicht initialisiert werden: %s auths.invalid_openIdConnectAutoDiscoveryURL=Ungültige Auto-Discovery-URL (dies muss eine gültige URL sein, die mit http:// oder https:// beginnt) config.server_config=Serverkonfiguration @@ -3526,7 +3526,7 @@ config.git_pull_timeout=Zeitlimit für Pull config.git_gc_timeout=Zeitlimit für GC config.log_config=Protokollierungs-Konfiguration -config.logger_name_fmt=Logger: %s +config.logger_name_fmt=Protokollierer: %s config.disabled_logger=Deaktiviert config.access_log_mode=Zugriffsprotokoll-Modus config.access_log_template=Zugriffsprotokoll-Vorlage @@ -3650,7 +3650,7 @@ mirror_sync_delete=hat die Referenz des Spiegels %[2]s in %[3]s#%[2]s genehmigt` reject_pull_request=`schlug Änderungen für %[3]s#%[2]s vor` publish_release=`veröffentlichte Release %[4]s in %[3]s` -review_dismissed=`verwarf das Review von %[4]s in %[3]s#%[2]s` +review_dismissed=`verwarf die Sichtung von %[4]s in %[3]s#%[2]s` review_dismissed_reason=Grund: create_branch=legte den Branch %[3]s in %[4]s an starred_repo=favorisierte %[2]s @@ -3765,9 +3765,9 @@ conda.registry=Richte diese Registry als Conda-Repository in deiner .conda conda.install=Um das Paket mit Conda zu installieren, führe den folgenden Befehl aus: container.details.type=Abbildtyp container.details.platform=Plattform -container.pull=Downloade das Container-Image aus der Kommandozeile: +container.pull=Lade das Container-Image von der Kommandozeile aus herunter: container.digest=Prüfsumme -container.multi_arch=Betriebsystem / Architektur +container.multi_arch=Betriebsystem/Architektur container.layers=Abbildebenen container.labels=Labels container.labels.key=Schlüssel @@ -3781,7 +3781,7 @@ debian.repository=Repository-Informationen debian.repository.distributions=Distributionen debian.repository.components=Komponenten debian.repository.architectures=Architekturen -generic.download=Downloade das Paket aus der Kommandozeile: +generic.download=Lade das Paket mit der Kommandozeile herunter: go.install=Installiere das Paket über die Kommandozeile: helm.registry=Diese Paketverwaltung über die Kommandozeile einrichten: helm.install=Nutze folgenden Befehl, um das Paket zu installieren: @@ -3813,10 +3813,10 @@ rubygems.install=Um das Paket mit gem zu installieren, führe den folgenden Befe rubygems.install2=oder füg es zum Gemfile hinzu: rubygems.dependencies.runtime=Laufzeitabhängigkeiten rubygems.dependencies.development=Entwicklungsabhängigkeiten -rubygems.required.ruby=Benötigt Ruby Version -rubygems.required.rubygems=Benötigt RubyGem Version +rubygems.required.ruby=Benötigt Ruby-Version +rubygems.required.rubygems=Benötigt RubyGem-Version swift.registry=Diese Registry über die Kommandozeile einrichten: -swift.install=Füge das Paket deiner Package.swift Datei hinzu: +swift.install=Füge das Paket deiner Package.swift-Datei hinzu: swift.install2=und führe den folgenden Befehl aus: vagrant.install=Um eine Vagrant-Box hinzuzufügen, führe den folgenden Befehl aus: settings.link=Dieses Paket einem Repository zuweisen @@ -3892,19 +3892,19 @@ alt.repository.architectures = Architekturen alt.repository.multiple_groups = Dieses Paket ist in verschiedenen Gruppen verfügbar. [secrets] -secrets=Secrets -description=Secrets werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden. -none=Noch keine Secrets vorhanden. -creation=Secret hinzufügen +secrets=Geheimnisse +description=Geheimnisse werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden. +none=Noch keine Geheimnisse vorhanden. +creation=Geheimnis hinzufügen creation.name_placeholder=Groß-/Kleinschreibung wird ignoriert, nur alphanumerische Zeichen oder Unterstriche, darf nicht mit GITEA_ oder GITHUB_ beginnen creation.value_placeholder=Beliebigen Inhalt eingeben. Leerzeichen am Anfang und Ende werden weggelassen. -creation.success=Das Secret „%s“ wurde hinzugefügt. -creation.failed=Secret konnte nicht hinzugefügt werden. -deletion=Secret entfernen -deletion.description=Das Entfernen eines Secrets kann nicht rückgängig gemacht werden. Fortfahren? -deletion.success=Das Secret wurde entfernt. -deletion.failed=Secret konnte nicht entfernt werden. -management=Secrets verwalten +creation.success=Das Geheimnis „%s“ wurde hinzugefügt. +creation.failed=Geheimnis konnte nicht hinzugefügt werden. +deletion=Geheimnis entfernen +deletion.description=Das Entfernen eines Geheimnisses kann nicht rückgängig gemacht werden. Fortfahren? +deletion.success=Das Geheimnis wurde entfernt. +deletion.failed=Geheimnis konnte nicht entfernt werden. +management=Geheimnisse verwalten [actions] actions=Actions diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index cce62685bf..c01d1464cb 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1882,7 +1882,6 @@ issues.content_history.created = created issues.content_history.delete_from_history = Delete from history issues.content_history.delete_from_history_confirm = Delete from history? issues.content_history.options = Options -issues.reference_link = Reference: %s issues.blocked_by_user = You cannot create issues in this repository because you are blocked by the repository owner. comment.blocked_by_user = Commenting is not possible because you are blocked by the repository owner or the author. issues.reopen.blocked_by_user = You cannot reopen this issue because you are blocked by the repository owner or the poster of this issue. diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index b94cb64af1..e071fa76f4 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -29,7 +29,7 @@ password=Пароль access_token=Токен доступу re_type=Підтвердження пароля captcha=CAPTCHA -twofa=Двофакторна авторизація +twofa=Двофакторна автентифікація twofa_scratch=Двофакторний одноразовий пароль passcode=Код доступу @@ -112,7 +112,7 @@ webauthn_error_unknown = Сталася невідома помилка. Буд webauthn_error_unable_to_process = Сервер не зміг обробити запит. webauthn_error_duplicated = Запит із наданим ключем безпеки відхилено. Впевніться, що цього ключа ще не зареєстровано. webauthn_error_empty = Ключ слід якось назвати. -new_project_column = Нова колонка +new_project_column = Новий стовпчик retry = Повторити rerun = Перезапустити rerun_all = Перезапустити всі завдання @@ -201,7 +201,7 @@ buttons.mention.tooltip = Згадати користувача чи коман buttons.ref.tooltip = Послатися на задачу чи на запит на злиття buttons.enable_monospace_font = Увімкнути моноширинний шрифт buttons.new_table.tooltip = Додати таблицю -table_modal.label.columns = Стовпці +table_modal.label.columns = Стовпчики table_modal.header = Додати таблицю table_modal.placeholder.header = Заголовок table_modal.placeholder.content = Вміст @@ -343,13 +343,13 @@ enable_update_checker = Увімкнути перевірку оновлень require_db_desc = Forgejo вимагає MySQL, PostgreSQL, SQLite3 чи TiDB (протокол MySQL). allow_only_external_registration = Дозволити реєстрацію тільки через зовнішні сервіси require_sign_in_view.description = Обмежити доступ до контенту лише користувачам, що увійшли. Гості зможуть лише відвідувати сторінки автентифікації. -password_algorithm_helper = Встановити алгоритм хешування паролів. Алгоритми мають різні вимоги та силу. Алгоритм argon2 є досить безпечним, проте споживає багато памʼяті та є недоречним для малих систем. +password_algorithm_helper = Установіть алгоритм хешування паролів. Алгоритми мають різні вимоги і стійкість. Алгоритм argon2 є досить безпечним, проте споживає багато памʼяті та є недоречним для малих систем. app_slogan = Гасло екземпляра app_slogan_helper = Уведіть гасло вашого екземпляра тут. Залиште порожнім, аби вимкнути. run_user_helper = Імʼя користувача операційної системи, від якого запущено Forgejo. Зауважте, що цей користувач повинен мати доступ до кореневої теки репозиторію. smtp_from_invalid = Адреса з «Відправляти email від імені» недійсна allow_dots_in_usernames = Дозволити використання крапки в іменах користувачів. Не впливає на облікові записи, що вже існують. -invalid_password_algorithm = Недійсний варіант алгоритму хешування паролів +invalid_password_algorithm = Недійсний алгоритм хешування паролів enable_update_checker_helper_forgejo = Наявність нових версій Forgejo періодично перевірятиметься через перевірку запису TXT DNS на release.forgejo.org. [home] @@ -734,7 +734,7 @@ applications=Додатки orgs=Організації repos=Репозиторії delete=Видалити обліковий запис -twofa=Двофакторна авторизація (TOTP) +twofa=Двофакторна автентифікація (TOTP) account_link=Прив'язані облікові записи organization=Організації @@ -1709,7 +1709,7 @@ 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 коміта повинен бути ID коміта в цільовій гілці +pulls.wrong_commit_id=ID коміту повинен бути ID коміту в цільовій гілці pulls.no_merge_desc=Цей запити на злиття неможливо злити, оскільки всі параметри об'єднання репозиторія вимкнено. pulls.no_merge_helper=Увімкніть параметри злиття в налаштуваннях репозиторія або злийте запити на злиття вручну. @@ -1727,7 +1727,7 @@ pulls.require_signed_wont_sign=Гілка вимагає підписаних к pulls.invalid_merge_option=Цей параметр злиття не можна використовувати для цього Pull Request'а. pulls.merge_conflict=Не вдалося об'єднати: при об'єднанні виник конфлікт. Підказка: спробуйте іншу стратегію pulls.merge_conflict_summary=Повідомлення про помилку -pulls.rebase_conflict=Не вдалося об'єднати: виник конфлікт під час перебазування коміта: %[1]s. Підказка: спробуйте іншу стратегію +pulls.rebase_conflict=Не вдалося об'єднати: виник конфлікт під час перебазування коміту: %[1]s. Підказка: спробуйте іншу стратегію pulls.rebase_conflict_summary=Повідомлення про помилку pulls.unrelated_histories=Не вдалося об'єднати: head та base злиття не мають спільної історії. Підказка: спробуйте іншу стратегію pulls.merge_out_of_date=Не вдалося об'єднати: base було оновлено, поки відбувалося об'єднання. Підказка: спробуйте знову. @@ -1896,7 +1896,7 @@ settings.mirror_settings.direction=Напрямок settings.mirror_settings.direction.pull=Pull settings.mirror_settings.direction.push=Push settings.mirror_settings.last_update=Останнє оновлення -settings.mirror_settings.push_mirror.none=Не налаштовано дзеркало push +settings.mirror_settings.push_mirror.none=Push-дзеркала не налаштовано settings.mirror_settings.push_mirror.remote_url=URL віддаленого репозиторію Git settings.mirror_settings.push_mirror.add=Додати push-дзеркало @@ -2343,7 +2343,7 @@ issues.author = Автор issues.author_helper = Цей користувач - автор. issues.close = Закрити задачу issues.role.owner_helper = Цей користувач є власником цього репозиторію. -settings.mirror_settings.docs.more_information_if_disabled = Докладніше про push та pull дзеркала можна дізнатися тут: +settings.mirror_settings.docs.more_information_if_disabled = Докладніше про push- та pull-дзеркала можна дізнатися тут: issues.comment.blocked_by_user = Ви не можете коментувати цю задачу, оскільки вас заблокував власник репозиторію або автор цієї задачі. editor.add_file = Додати файл from_comment = (коментар) @@ -2431,7 +2431,7 @@ pulls.is_ancestor = Цю гілку вже включено в цільову г pulls.has_merged = Помилка: запит на злиття вже об'єднано, неможливо об'єднати знову чи змінити цільову гілку. pulls.head_out_of_date = Не вдалося об'єднати: head було оновлено, поки відбувалося об'єднання. Підказка: спробуйте знову. no_eol.tooltip = У цьому файлі відсутній символ закінчення рядка (EOL) у кінці. -settings.trust_model.committer.desc = Допустимі підписи будуть позначатися як «довірені», тільки якщо вони відповідають автору коміта, в іншому випадку вони позначатимуться як «невідповідні». Це змусить Forgejo бути автором підписаних комітів, а фактичного автора зазначати в трейлерах «Co-authored-by» і «Co-committed-by» в описі коміта. Типовий ключ Forgejo повинен відповідати користувачу в базі даних. +settings.trust_model.committer.desc = Допустимі підписи будуть позначатися як «довірені», тільки якщо вони відповідають авторові коміту, в іншому випадку вони позначатимуться як «невідповідні». Це змусить Forgejo бути автором підписаних комітів, а фактичного автора зазначати в трейлерах «Co-authored-by» і «Co-committed-by» в описі коміту. Типовий ключ Forgejo повинен відповідати користувачу в базі даних. pulls.clear_merge_message_hint = Очищення повідомлення про об'єднання видалить лише вміст повідомлення коміту і збереже згенеровані git-трейлери, такі як «Co-Authored-By…». branch.delete_branch_has_new_commits = Гілку «%s» не можна видалити, оскільки після об'єднання було додано нові коміти. settings.graphql_url = Посилання GraphQL @@ -2514,7 +2514,7 @@ projects.column.set_default = Установити за замовчування settings.federation_following_repos = URL-адреси відстежуваних репозиторіїв. Через «;», без пробілів. settings.federation_not_enabled = Федерацію вимкнено у вашому екземплярі. settings.federation_settings = Налаштування федерації -signing.wont_sign.nokey = Цей екземпляр не має ключа для підписання цього коміта. +signing.wont_sign.nokey = Цей екземпляр не має ключа для підписання цього коміту. settings.federation_apapiurl = URL федерації цього репозиторію. Скопіюйте її та вставте в налаштування федерації іншого репозиторію як URL-адресу відстежуваного репозиторію. fork_branch = Гілка, яку буде клоновано у форк already_forked = Ви вже створили форк %s @@ -2554,7 +2554,7 @@ activity.navbar.pulse = Пульс open_with_editor = Відкрити в %s commits.view_single_diff = Переглянути зміни до цього файлу, внесені у цьому коміті pulls.editable = Редаговане -pulls.editable_explanation = Цей запит на злиття дозволяє редагування від розробників. Ви можете зробити свій внесок безпосередньо до нього. +pulls.editable_explanation = Цей запит на злиття дозволено редагувати супроводжувачам. Ви можете зробити свій внесок безпосередньо до нього. admin.failed_to_replace_flags = Не вдалося замінити прапорці репозиторія admin.enabled_flags = Для репозиторія ввімкнено прапорці: admin.flags_replaced = Прапорці репозиторія замінено @@ -2773,6 +2773,58 @@ issues.closed_by = від %[3]s закрито %[1]s issues.action_check = Поставити/зняти позначку issues.action_check_all = Поставити/зняти позначку з усіх елементів vendored = Сторонній +blame.ignore_revs.failed = Не вдалося проігнорувати зміни в .git-blame-ignore-revs. +blame.ignore_revs = Зміни в .git-blame-ignore-revs ігноруються. Натисніть тут, щоб обійти це і переглянути авторство у звичайному вигляді. +editor.new_branch_name = Укажіть назву нової гілки для цього коміту +projects.column.deletion_desc = Видалення стовпчика проєкту призведе до переміщення всіх пов'язаних із ним задач до стовпчика за замовчуванням. Продовжити? +signing.wont_sign.approved = Злиття не буде підписано, оскільки запит на злиття не схвалено. +pulls.allow_edits_from_maintainers = Дозволити редагування від супроводжувачів +pulls.showing_only_single_commit = Показано тільки зміни коміту %[1]s +pulls.showing_specified_commit_range = Показано тільки зміни між %[1]s..%[2]s +pulls.blocked_by_outdated_branch = Цей запит на злиття заблоковано, оскільки він застарів. +pulls.blocked_by_changed_protected_files_n = Цей запит на злиття заблоковано, оскільки він змінює захищені файли: +pulls.auto_merge_newly_scheduled = Заплановано об'єднати запит на злиття після успішного завершення всіх перевірок. +pulls.auto_merge_newly_scheduled_comment = `планує автоматично об'єднати цей запит на злиття після успішного завершення всіх перевірок %[1]s` +comments.edit.already_changed = Не вдається зберегти зміни. Схоже, що хтось інший уже змінив вміст коментаря. Оновіть сторінку і спробуйте відредагувати ще раз, щоб уникнути перезапису чужих змін +pulls.auto_merge_canceled_schedule_comment = `скасовує автоматичне об'єднання цього запиту на злиття після успішного завершення всіх перевірок %[1]s` +signing.wont_sign.pubkey = Коміт не буде підписано, оскільки у вас немає публічного ключа, пов'язаного з вашим обліковим записом. +signing.wont_sign.basesigned = Злиття не буде підписано, оскільки не підписано базовий коміт. +signing.wont_sign.headsigned = Злиття не буде підписано, оскільки не підписано головний коміт. +projects.column.new_submit = Створити стовпчик +settings.authorization_header_desc = За наявності буде включено як заголовок авторизації для запитів. Приклади: %s. +template.git_hooks_tooltip = Наразі ви не можете змінювати або видаляти додані Git-хуки. Вибирайте лише якщо ви довіряєте репозиторію шаблону. +projects.column.edit = Редагувати стовпчик +projects.column.set_default_desc = Призначити цей стовпчик за замовчуванням для задач і запитів на злиття без категорії +projects.column.new = Новий стовпчик +projects.column.delete = Видалити стовпчик +pulls.blocked_by_official_review_requests = Цей запит на злиття заблоковано, оскільки йому бракує схвалення від одного або кількох офіційних рецензентів. +pulls.auto_merge_has_pending_schedule = %[1]s планує автоматично об'єднати цей запит на злиття після успішного завершення всіх перевірок %[2]s. +signing.wont_sign.commitssigned = Злиття не буде підписано, оскільки всі пов'язані з ним коміти не підписані. +settings.authorization_header = Заголовок авторизації +issues.archived_label_description = (Архівна) %s +issues.reaction.add = Додати реакцію +issues.reaction.alt_add = Додати реакцію %[1]s до коментаря. +issues.reaction.alt_remove = Прибрати реакцію %[1] з коментаря. +migrate.github_token_desc = Ви можете ввести тут один або кілька токенів через кому, щоб пришвидшити міграцію в обхід обмеження частоти звернень до API GitHub. ОБЕРЕЖНО: зловживання цією функцією може порушити політику постачальника послуг і призвести до блокування облікового запису. +issues.edit.already_changed = Не вдається зберегти зміни. Схоже, що хтось інший уже змінив вміст задачі. Оновіть сторінку і спробуйте відредагувати ще раз, щоб уникнути перезапису чужих змін +pulls.edit.already_changed = Не вдається зберегти зміни. Схоже, що хтось інший уже змінив вміст запиту на злиття. Оновіть сторінку і спробуйте відредагувати ще раз, щоб уникнути перезапису чужих змін +issues.reaction.alt_many = %[1]s і ще %[2]d реагують %[3]s. +settings.pulls.default_allow_edits_from_maintainers = За замовчуванням дозволити редагування від супроводжувачів +pulls.blocked_by_changed_protected_files_1 = Цей запит на злиття заблоковано, оскільки він змінює захищений файл: +pulls.delete.text = Ви дійсно хочете видалити цей запит на злиття? (Весь його вміст буде остаточно видалено. Можливо, варто його закрити і зберегти в архіві) +pulls.blocked_by_rejection = Цей запит на злиття містить зміни, запропоновані офіційним рецензентом. +signing.wont_sign.parentsigned = Цей коміт не буде підписано, оскільки не підписано батьківський коміт. +settings.ignore_stale_approvals = Ігнорувати застарілі схвалення +pulls.blocked_by_approvals = Цей запит на злиття ще не має достатньої кількості схвалень. Отримано %d з %d схвалень. +issues.delete.text = Ви дійсно хочете видалити цю задачу? (Весь її вміст буде остаточно видалено. Можливо, варто її закрити і зберегти в архіві) +signing.wont_sign.twofa = Щоб підписувати коміти, у вас повинна бути ввімкнена двофакторна автентифікація. +settings.mirror_settings.docs = Налаштуйте свій репозиторій на автоматичну синхронізацію комітів, тегів і гілок з іншим репозиторієм. +settings.mirror_settings.docs.disabled_push_mirror.instructions = Налаштуйте свій проєкт на автоматичне отримання комітів, тегів і гілок з іншого репозиторію. +settings.mirror_settings.docs.disabled_push_mirror.info = Push-дзеркала вимкнено адміністратором сайту. +settings.mirror_settings.docs.disabled_pull_mirror.instructions = Налаштуйте свій проєкт на автоматичне надсилання комітів, тегів і гілок до іншого репозиторію. Pull-дзеркала вимкнено адміністратором сайту. +issues.label_templates.fail_to_load_file = Не вдалося завантажити файл шаблону міток «%s»: %v +migrate.github.description = Перенесіть дані з github.com або сервера GitHub Enterprise. +migrate.cancel_migrating_confirm = Бажаєте скасувати перенесення? [graphs] contributors.what = внески @@ -3016,7 +3068,7 @@ users.prohibit_login=Заблокований обліковий запис users.is_admin=Обліковий запис адміністратора users.is_restricted=Обмежений users.allow_git_hook=Може створювати Git-хуки -users.allow_git_hook_tooltip=Git хуки виконуються від імені користувача OS сервісу Forgejo і мають однаковий рівень доступу до хоста. Як результат, користувачі з доступом до Git-хуків можуть отримати доступ і змінювати всі репозиторії Forgejo, а також базу даних, що використовуються в Forgejo. Отже, вони також здатні отримати права адміністратора Forgejo. +users.allow_git_hook_tooltip=Git-хуки виконуються від імені користувача ОС, від якого запущено Forgejo, і мають той самий рівень доступу до хоста. Таким чином, користувачі зі спеціальними правами Git-хуків можуть отримати доступ і змінювати всі репозиторії Forgejo, а також базу даних Forgejo. Вони також здатні отримати права адміністратора Forgejo. users.allow_import_local=Може імпортувати локальні репозиторії users.allow_create_organization=Може створювати організації users.update_profile=Оновити обліковий запис @@ -3170,7 +3222,7 @@ auths.tip.discord=Зареєструйте новий додаток на %s auths.tip.yandex=Створіть новий додаток на %s. У розділі «Yandex.Passport API» виберіть такі дозволи: «Доступ до адреси електронної пошти», «Доступ до аватара» і «Доступ до імені користувача, імені та прізвища, статі» auths.tip.mastodon=Введіть URL спеціального екземпляра для екземпляра mastodon, який ви хочете автентифікувати за допомогою (або використовувати за замовчуванням) auths.edit=Редагувати джерело автентифікації -auths.activated=Це джерело авторизації активоване +auths.activated=Це джерело автентифікація активоване auths.update_success=Параметри аутентифікації оновлені. auths.update=Оновити джерело автентифікації auths.delete=Видалити джерело автентифікації @@ -3196,7 +3248,7 @@ config.repo_root_path=Шлях до кореня репозиторію config.lfs_root_path=Кореневий шлях LFS config.log_file_root_path=Шлях до лог файлу config.script_type=Тип скрипта -config.reverse_auth_user=Ім'я користувача для авторизації на reverse proxy +config.reverse_auth_user=Користувач для авторизації на зворотному проксі config.ssh_config=Конфігурація SSH config.ssh_enabled=Увімкнено @@ -3423,6 +3475,12 @@ config.mailer_smtp_addr = Адреса SMTP dashboard.update_checker = Перевірка оновлень auths.map_group_to_team_removal = Видаляти користувачів із синхронізованих команд, якщо користувачі не належать до відповідної групи LDAP auths.enable_ldap_groups = Увімкнути групи LDAP +auths.unable_to_initialize_openid = Не вдалося ініціалізувати постачальника OpenID Connect: %s +auths.new_success = Метод автентифікації «%s» додано. +config.cache_test_slow = Перевірку кешу завершено успішно, але відповідь повільна: %s. +config.cache_test_succeeded = Перевірку кешу завершено успішно, відповідь отримано через %s. +config.cache_test = Перевірити кеш +config.cache_test_failed = Не вдалося перевірити кеш: %v. [action] @@ -3704,7 +3762,7 @@ variables.management = Керування змінними variables.id_not_exist = Змінної з ідентифікатором %d не існує. variables.edit = Редагувати змінну runs.expire_log_message = Журнали очищено, тому що вони були занадто старі. -runs.empty_commit_message = (порожнє повідомлення коміта) +runs.empty_commit_message = (порожнє повідомлення коміту) runners.status.unspecified = Невідомо runs.status_no_select = Усі стани runs.status = Стан @@ -3826,6 +3884,7 @@ wiki.write = Писати: створювати, оновлювати т issues.read = Читати: дивитись і створювати задачі та коментарі. wiki.read = Читати: переглядати вбудовану вікі та її історію. actions.write = Писати: вручну запускати, перезапускати, скасовувати або схвалювати конвеєри CI/CD в очікуванні. +projects.write = Писати: створювати проєкти і стовпчики та редагувати їх. [munits.data] pib = ПіБ diff --git a/options/locale_next/locale_ar.json b/options/locale_next/locale_ar.json index cef0f06e23..eca76a5ba7 100644 --- a/options/locale_next/locale_ar.json +++ b/options/locale_next/locale_ar.json @@ -4,6 +4,138 @@ "home.explore_repos": "اكتشف المستودعات", "home.explore_users": "اكتشف المستخدمين", "home.explore_orgs": "اكتشف المنظمات", - "moderation.abuse_category.illegal_content": "المحتوى غير المشروع", - "moderation.abuse_category.malware": "برمجية خبيثة" + "moderation.abuse_category.illegal_content": "محتوى غير مشروع", + "moderation.abuse_category.malware": "برمجية خبيثة", + "relativetime.now": "الآن", + "relativetime.1month": "الشهر الفائت", + "relativetime.2weeks": "منذ أسبوعين", + "search.milestone_kind": "معالم البحث…", + "moderation.abuse_category.other_violations": "انتهاكات أخرى لقواعد المنصة", + "repo.issue_indexer.title": "مفهرس الإبلاغات", + "incorrect_root_url": "تم تكوين هذه النسخة من Forgejo لتعمل على العنوان \"%s\". أنت تقوم حاليًا بتصفّح Forgejo عبر رابط مختلف، مما قد يتسبب في تعطل بعض أجزاء التطبيق. يتم تحديد الرابط الرسمي (canonical URL) من قِبل مسؤولي Forgejo من خلال إعداد `ROOT_URL` في ملف `app.ini`.", + "error.not_found.title": "الصفحة غير موجودة", + "themes.names.forgejo-auto": "فورجيو (اتبع سمة النظام)", + "themes.names.forgejo-light": "فورجيجو المضيء", + "themes.names.forgejo-dark": "فورجيجو الداكن", + "stars.list.none": "لم يقم أحد بتمييز هذا المستودع بنجمة.", + "watch.list.none": "لا أحد يشاهد هذا المستودع.", + "followers.incoming.list.self.none": "لا أحد يتابع ملفك الشخصي.", + "followers.incoming.list.none": "لا أحد يتابع هذا المستخدم.", + "followers.outgoing.list.self.none": "أنت لا تتبع أي شخص.", + "relativetime.1day": "الأمس", + "followers.outgoing.list.none": "لا يتابع %s أي شخص.", + "relativetime.1week": "أخر أسبوع", + "relativetime.2days": "منذ يومين", + "relativetime.2months": "منذ شهرين", + "relativetime.1year": "السنة الفائتة", + "relativetime.2years": "منذ سنتين", + "repo.form.cannot_create": "بلغت جميع المساحات التي يمكنك إنشاء مستودعات بها حدها.", + "alert.asset_load_failed": "تعذّر تحميل ملفات الأصول من {path}. تأكد من أن الملفات متاحة للوصول.", + "settings.visibility.description": "رؤية ملفك الشخصي تؤثر في قدرة الآخرين على الوصول إلى مستودعاتك غير الخاصة. اعرف المزيد", + "relativetime.mins": { + "zero": "الآن", + "one": "منذ دقيقة مضت", + "two": "منذ دقيقتين مضت", + "few": "منذ %d دقائق مضت", + "many": "منذ %d دقيقة مضت", + "other": "منذ %d دقيقة مضت" + }, + "relativetime.hours": { + "zero": "الآن", + "one": "منذ ساعة", + "two": "منذ ساعتين", + "few": "منذ %d ساعات", + "many": "منذ %d ساعة", + "other": "منذ %d ساعة" + }, + "moderation.report_remarks": "الملاحظات", + "repo.diff.commit.next-short": "التالي", + "repo.diff.commit.previous-short": "السابق", + "admin.dashboard.cleanup_offline_runners": "تنظيف وحدات التشغيل غير المتصلة", + "relativetime.days": { + "zero": "اليوم", + "one": "منذ يوم واحد", + "two": "منذ يومين", + "few": "منذ %d أيام", + "many": "منذ %d يوماً", + "other": "منذ %d يوماً" + }, + "relativetime.weeks": { + "zero": "هذا الأسبوع", + "one": "منذ أسبوع واحد", + "two": "منذ أسبوعين", + "few": "منذ %d أسابيع", + "many": "منذ %d أسبوعاً", + "other": "منذ %d أسبوعاً" + }, + "relativetime.years": { + "zero": "هذه السنة", + "one": "منذ سنة واحدة", + "two": "منذ سنتين", + "few": "منذ %d سنوات", + "many": "منذ %d سنة", + "other": "منذ %d سنة" + }, + "repo.settings.push_mirror.branch_filter.label": "تصفية الفرع (اختياري)", + "repo.settings.push_mirror.branch_filter.description": "الفروع المطلوب عكسها. اترك الحقل فارغًا لعكس جميع الفروع. راجع توثيق %[2]s للاطلاع على الصيغة. أمثلة: main, release/*", + "og.repo.summary_card.alt_description": "بطاقة تلخيصية للمستودع %[1]، موصوفة بـ %[1]: %[2]s", + "meta.last_line": "شكرًا لك على ترجمة Forgejo! هذا السطر لا يراه المستخدمون ولكنه يخدم أغراضًا أخرى في إدارة الترجمة. يمكنك وضع حقيقة ممتعة في الترجمة بدلاً من ترجمتها.", + "relativetime.future": "في المستقبل", + "avatar.constraints_hint": "لا يمكن أن يتجاوز حجم الصورة الشخصية المخصصة %[1]s، ولا أبعادها عن %[2]d×%[3]d بكسل", + "repo.pulls.merged_title_desc": { + "zero": "لم دمج أي إيداع من %[2]s إلى %[3]s %[4]s", + "one": "تم دمج إيداع واحد من %[2]s إلى %[3]s %[4]s", + "two": "تم دمج إيداعين اثنين من %[2]s إلى %[3]s %[4]s", + "few": "تم دمج %[1]d إيداعات من %[2]s إلى %[3]s %[4]s", + "many": "تم دمج %[1]d إيداعاً من %[2]s إلى %[3]s %[4]s", + "other": "تم دمج %[1]d إيداعاً من %[2]s إلى %[3]s %[4]s" + }, + "relativetime.months": { + "zero": "هذا الشهر", + "one": "منذ شهر", + "two": "منذ شهرين", + "few": "منذ %d أشهر", + "many": "منذ %d شهراً", + "other": "منذ %d شهراً" + }, + "repo.pulls.title_desc": { + "zero": "لا يريد دمج أي إيداع من %[2]s إلى %[3]s", + "one": "يريد دمج إيداع واحد من %[2]s إلى %[3]s", + "two": "يريد دمج إيداعين من %[2]s إلى %[3]s", + "few": "يريد دمج %[1]d إيداعات من %[2]s إلى %[3]s", + "many": "يريد دمج %[1]d إيداعًا من %[2]s إلى %[3]s", + "other": "يريد دمج %[1]d إيداعًا من %[2]s إلى %[3]s" + }, + "mail.actions.run_info_sha": "إيداع: %[1]s", + "keys.gpg.link": "مفاتيح GPG", + "moderation.abuse_category.spam": "غير مرغوب به", + "keys.ssh.link": "مفاتيح SSH", + "profile.edit.link": "عدِّل ملف التعريف", + "moderation.abuse_category": "الفئة", + "moderation.abuse_category.placeholder": "حدد الفئة", + "moderation.report_remarks.placeholder": "يُرجى تقديم بعض التفاصيل المتعلقة بالإساءة التي أبلغت عنها.", + "moderation.submit_report": "إرسال التقرير", + "moderation.reporting_failed": "تعذر إرسال تقرير إساءة الاستخدام الجديد: %v", + "moderation.reported_thank_you": "شكراُ لك على تقريرك. وقد تم إبلاغ الإدارة به.", + "mail.actions.run_info_trigger": "تم تشغيله بسبب: %[1]s عبر: %[2]s", + "install.invalid_lfs_path": "غير قادر على إنشاء جذر LFS في المسار المحدد: %[1]s", + "alert.range_error": " يجب أن يكون رقمًا بين %[1]s و %[2]s.", + "mail.actions.not_successful_run_subject": "سير العمل %[1]s فشل في المستودت %[2]s", + "mail.actions.successful_run_after_failure": "تم استعادة سير العمل %[1]s في المستودع %[2]s", + "mail.actions.not_successful_run": "فشل سير العمل %[1]s في المستودع %[2]s", + "mail.actions.run_info_cur_status": "حالة هذا التشغيل: %[1]s (تم تحديثها من %[2]s للتو)", + "mail.actions.run_info_previous_status": "حالة التشغيل السابقة: %[1]s", + "discussion.locked": "تم إغلاق هذه المناقشة. يقتصر التعليق على المساهمين فقط.", + "editor.textarea.tab_hint": "السطر مُزاح بالفعل. اضغط Tab مرة أخرى أو Escape لمغادرة المحرر.", + "editor.textarea.shift_tab_hint": "لا توجد مسافة بادئة في هذا السطر. اضغط Shift + Tab مرة أخرى أو Escape لمغادرة المحرر.", + "profile.actions.tooltip": "إجراءات إضافية", + "moderation.report_content": "محتوى التقارير", + "moderation.report_abuse_form.header": "الإبلاغ عن الإساءة إلى المسؤول", + "moderation.report_abuse_form.details": "يتعين استخدام هذا النموذج للإبلاغ عن المستخدمين الذين ينشئون ملفات تعريف ، أو مستودعات ، أو إبلاغات ، أو تعليقات ، أو يتصرفون بشكل غير لائق.", + "moderation.report_abuse_form.invalid": "معاملا غير صالحة", + "moderation.report_abuse_form.already_reported": "‍لقد قمت بالفعل بالإبلاغ عن هذا المحتوى", + "moderation.report_abuse": "الإبلاغ عن إساءة الاستخدام", + "feed.atom.link": "موجز Atom", + "admin.config.moderation_config": "تهيئة الإشراف", + "mail.actions.successful_run_after_failure_subject": "تم استعادة سير العمل %[1]s في المستودع %[2]s" } diff --git a/options/locale_next/locale_be.json b/options/locale_next/locale_be.json index 40dfec0b41..c8ff00bd87 100644 --- a/options/locale_next/locale_be.json +++ b/options/locale_next/locale_be.json @@ -1,3 +1,8 @@ { - "moderation.abuse_category.malware": "Шкодная праграма" + "moderation.abuse_category.malware": "Шкодная праграма", + "home.welcome.no_activity": "Няма падзей", + "home.welcome.activity_hint": "У вашай стужцы пакуль што нічога няма. Вашыя дзеяньні ды падзеі з рэпазыторыяў зьявяцца тут.", + "home.explore_repos": "Агляд рэпазыторыяў", + "home.explore_users": "Агляд карыстальнікаў", + "home.explore_orgs": "Агляд арганізацый" } diff --git a/options/locale_next/locale_cs-CZ.json b/options/locale_next/locale_cs-CZ.json index 3ce42e6bb0..b47c594348 100644 --- a/options/locale_next/locale_cs-CZ.json +++ b/options/locale_next/locale_cs-CZ.json @@ -111,5 +111,7 @@ "feed.atom.link": "Zdroj Atom", "keys.ssh.link": "Klíče SSH", "og.repo.summary_card.alt_description": "Karta se souhrnem repozitáře %[1]s, popsaným jako: %[2]s", - "mail.actions.run_info_sha": "Revize: %[1]s" + "mail.actions.run_info_sha": "Revize: %[1]s", + "repo.settings.push_mirror.branch_filter.label": "Filtr větve (nepovinný)", + "repo.settings.push_mirror.branch_filter.description": "Větve, které mají být zrcadleny. Ponechte prázdné pro zrcadlení všech větví. Syntaxi naleznete v dokumentaci %[2]s. Příklady: main, release/*" } diff --git a/options/locale_next/locale_de-DE.json b/options/locale_next/locale_de-DE.json index 5d670aeedf..5a3ceef7e5 100644 --- a/options/locale_next/locale_de-DE.json +++ b/options/locale_next/locale_de-DE.json @@ -90,11 +90,11 @@ "followers.outgoing.list.none": "%s folgt niemanden.", "stars.list.none": "Niemand hat dieses Repo favorisiert.", "followers.incoming.list.none": "Niemand folgt diesem Benutzer.", - "editor.textarea.tab_hint": "Zeile bereits eingerückt. Drücke nochmals Tab oder Escape um den Editor zu verlassen.", - "editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals Shift + Tab oder Escape um den Editor zu verlassen.", - "admin.dashboard.cleanup_offline_runners": "Aufräumen der offline Runner", + "editor.textarea.tab_hint": "Zeile bereits eingerückt. Drücke nochmals Tab oder Escape, um den Editor zu verlassen.", + "editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals Shift + Tab oder Escape, um den Editor zu verlassen.", + "admin.dashboard.cleanup_offline_runners": "Aufräumen der Offline-Runner", "settings.visibility.description": "Die Profilsichtbarkeit beeinflusst die Möglichkeit anderer, auf deine nicht-privaten Repositorys zuzugreifen. Erfahre mehr", - "avatar.constraints_hint": "Individuelles Profilbild darf %[1]s in der Größe nicht überschreiten, und nicht größer als %[2]dx%[3]d Pixel sein", + "avatar.constraints_hint": "Individuelles Profilbild darf %[1]s in der Größe nicht überschreiten, und nicht größer als %[2]d×%[3]d Pixel sein", "repo.diff.commit.next-short": "Nächste", "repo.diff.commit.previous-short": "Vorherige", "profile.edit.link": "Profil bearbeiten", @@ -103,5 +103,7 @@ "keys.gpg.link": "GPG-Schlüssel", "profile.actions.tooltip": "Mehr Aktionen", "og.repo.summary_card.alt_description": "Zusammenfassungskarte des Repositorys %[1]s, beschrieben als %[2]s", - "mail.actions.run_info_sha": "Commit: %[1]s" + "mail.actions.run_info_sha": "Commit: %[1]s", + "repo.settings.push_mirror.branch_filter.label": "Branch-Filter (optional)", + "repo.settings.push_mirror.branch_filter.description": "Zu spiegelnde Branches. Leer lassen, um alle Branches zu spiegeln. Siehe die „%[2]s“-Dokumentation für die Syntax. Beispiele: main, release/*" } diff --git a/options/locale_next/locale_en-US.json b/options/locale_next/locale_en-US.json index 1778a1fc6c..3c877ff627 100644 --- a/options/locale_next/locale_en-US.json +++ b/options/locale_next/locale_en-US.json @@ -56,7 +56,7 @@ "repo.issue_indexer.title": "Issue Indexer", "search.milestone_kind": "Search milestones…", "repo.settings.push_mirror.branch_filter.label": "Branch filter (optional)", - "repo.settings.push_mirror.branch_filter.description": "Branches to be mirrored. Leave blank to mirror all branches. See %[2]s documentation for syntax. Examples: main, release/*", + "repo.settings.push_mirror.branch_filter.description": "Branches to be mirrored. Leave blank to mirror all branches. See %[2]s documentation for syntax. Examples: main, release/*", "incorrect_root_url": "This Forgejo instance is configured to be served on \"%s\". You are currently viewing Forgejo through a different URL, which may cause parts of the application to break. The canonical URL is controlled by Forgejo admins via the ROOT_URL setting in the app.ini.", "themes.names.forgejo-auto": "Forgejo (follow system theme)", "themes.names.forgejo-light": "Forgejo light", @@ -99,6 +99,7 @@ "repo.diff.commit.next-short": "Next", "repo.diff.commit.previous-short": "Prev", "discussion.locked": "This discussion has been locked. Commenting is limited to contributors.", + "discussion.sidebar.reference": "Reference", "editor.textarea.tab_hint": "Line already indented. Press Tab again or Escape to leave the editor.", "editor.textarea.shift_tab_hint": "No indentation on this line. Press Shift + Tab again or Escape to leave the editor.", "admin.dashboard.cleanup_offline_runners": "Cleanup offline runners", diff --git a/options/locale_next/locale_fil.json b/options/locale_next/locale_fil.json index 2c62514648..6ec601c538 100644 --- a/options/locale_next/locale_fil.json +++ b/options/locale_next/locale_fil.json @@ -1,6 +1,6 @@ { "repo.pulls.merged_title_desc": { - "one": "isinali ang %[1]d commit mula%[2]s patungong %[3]s %[4]s", + "one": "isinali ang %[1]d commit mula %[2]s patungong %[3]s %[4]s", "other": "isinali ang %[1]d mga commit mula sa %[2]s patungong %[3]s %[4]s" }, "repo.pulls.title_desc": { @@ -21,7 +21,7 @@ "alert.asset_load_failed": "Nabigong i-load ang mga asset file mula sa {path}. Siguraduhin na maa-access ang mga asset file.", "install.invalid_lfs_path": "Nabigong gawin ang LFS root sa tinakdang path: %[1]s", "alert.range_error": " dapat ay numero sa pagitan ng %[1]s at %[2]s.", - "meta.last_line": "Every day, I imagine a future where I can be with you. In my hand is a pen that will write a poem of me and you. The ink flows down into a dark puddle... Just move your hand, write the way into his heart. But in this world of infinite choices. What will it take just to find that special day? Have I found everybody a fun assignment to do today? When you're here, everything that we do is fun for them anyway... When I can't even read my own feelings. What good are words when a smile says it all? And if this world won't write me an ending... What will it take just for me to have it all? Does my pen only write bitter words for those who are dear to me? Is it love if I take you, or is it love if I set you free? The ink flows down into a dark puddle... How can I write love into reality? If I can't hear the sound of your heartbeat What do you call love in your reality? And in your reality, if I don't know how to love you... I'll leave you be.", + "meta.last_line": "Every day, I imagine a future where I can be with you. In my hand is a pen that will write a poem of me and you. The ink flows down into a dark puddle... Just move your hand, write the way into his heart. But in this world of infinite choices, what will it take just to find that special day? Have I found everybody a fun assignment to do today? When you're here, everything that we do is fun for them anyway... When I can't even read my own feelings, what good are words when a smile says it all? And if this world won't write me an ending, what will it take just for me to have it all? Does my pen only write bitter words for those who are dear to me? Is it love if I take you, or is it love if I set you free? The ink flows down into a dark puddle... How can I write love into reality? If I can't hear the sound of your heartbeat, what do you call love in your reality? And in your reality, if I don't know how to love you... I'll leave you be.", "mail.actions.successful_run_after_failure": "Na-recover ang workflow na %[1]s sa repositoryong %[2]s", "mail.actions.not_successful_run": "Nabigo ang workflow na %[1]s sa repositoryong %[2]s", "mail.actions.run_info_previous_status": "Nakaraang Status ng Run: %[1]s", @@ -102,5 +102,8 @@ "keys.ssh.link": "Mga SSH key", "keys.gpg.link": "Mga GPG key", "profile.actions.tooltip": "Higit pang mga aksyon", - "og.repo.summary_card.alt_description": "Card ng pangkalahatang ideya ng repositoryong %[1]s, inilalarawan bilang: %[2]s" + "og.repo.summary_card.alt_description": "Card ng pangkalahatang ideya ng repositoryong %[1]s, inilalarawan bilang: %[2]s", + "mail.actions.run_info_sha": "Commit: %[1]s", + "repo.settings.push_mirror.branch_filter.label": "Filter ng branch (opsyonal)", + "repo.settings.push_mirror.branch_filter.description": "Mga branch na imi-mirror. Iwanang walang laman para i-mirror ang lahat ng mga branch. Tignan ang dokumentasyon ng %[2]s para sa syntax. Halimbawa: main, your-reality, release/*" } diff --git a/options/locale_next/locale_lv-LV.json b/options/locale_next/locale_lv-LV.json index 22b80f2fad..5503763dd3 100644 --- a/options/locale_next/locale_lv-LV.json +++ b/options/locale_next/locale_lv-LV.json @@ -111,5 +111,7 @@ "keys.ssh.link": "SSH atslēgas", "keys.gpg.link": "GPG atslēgas", "og.repo.summary_card.alt_description": "Glabātavas %[1]s kopsavilkuma kartīte, aprakstīta kā: %[2]s", - "mail.actions.run_info_sha": "Iesūtījums: %[1]s" + "mail.actions.run_info_sha": "Iesūtījums: %[1]s", + "repo.settings.push_mirror.branch_filter.description": "Zarus, kurus spoguļot. Atstāt tukšu, lai spoguļotu visus zarus. Pierakstu skatīt %[2]s dokumentācijā. Piemēri: main, release/*", + "repo.settings.push_mirror.branch_filter.label": "Zaru atlasītājs (izvēles)" } diff --git a/options/locale_next/locale_nds.json b/options/locale_next/locale_nds.json index 20c1208c42..4a796aaee9 100644 --- a/options/locale_next/locale_nds.json +++ b/options/locale_next/locale_nds.json @@ -103,5 +103,7 @@ "profile.actions.tooltip": "Mehr Aktioonen", "profile.edit.link": "Profil bewarken", "og.repo.summary_card.alt_description": "Tosamenfatens-Kaart vun de Repositorium %[1]s, beschrieven as: %[2]s", - "mail.actions.run_info_sha": "Kommitteren: %[1]s" + "mail.actions.run_info_sha": "Kommitteren: %[1]s", + "repo.settings.push_mirror.branch_filter.description": "Twiegen tum Spegeln. Laat dat leeg, um all Twiegen to spegeln. Lees de %[2]s-Dokumenteren för de Syntax. Bispölen: main, release/*", + "repo.settings.push_mirror.branch_filter.label": "Twieg-Filter (wenn du willst)" } diff --git a/options/locale_next/locale_nl-NL.json b/options/locale_next/locale_nl-NL.json index e049db3d41..7491458957 100644 --- a/options/locale_next/locale_nl-NL.json +++ b/options/locale_next/locale_nl-NL.json @@ -103,5 +103,7 @@ "repo.diff.commit.previous-short": "Vorige", "avatar.constraints_hint": "Eigen avatars mogen niet groter zijn dan %[1]s in grootte of groter zijn dan %[2]dx%[3]d pixels", "og.repo.summary_card.alt_description": "Samenvattingsoverzicht van repositorie %[1]s, omschreven als: %[2]s", - "mail.actions.run_info_sha": "Commit: %[1]s" + "mail.actions.run_info_sha": "Commit: %[1]s", + "repo.settings.push_mirror.branch_filter.label": "Branch filter (optioneel)", + "repo.settings.push_mirror.branch_filter.description": "Branches die gespiegeld moeten worden. Laat het laag om alle branches te spiegelen. Zie %[2]s documentatie voor de syntax. Voorbeeld: main, release/*" } diff --git a/options/locale_next/locale_pt-BR.json b/options/locale_next/locale_pt-BR.json index 6ed6c5defd..80395b020b 100644 --- a/options/locale_next/locale_pt-BR.json +++ b/options/locale_next/locale_pt-BR.json @@ -111,5 +111,7 @@ "og.repo.summary_card.alt_description": "Cartão de resumo do repositório %[1]s, descrito como: %[2]s", "profile.actions.tooltip": "Mais Actions", "keys.ssh.link": "Chaves SSH", - "mail.actions.run_info_sha": "Commit: %[1]s" + "mail.actions.run_info_sha": "Commit: %[1]s", + "repo.settings.push_mirror.branch_filter.label": "Filtro de branches (opcional)", + "repo.settings.push_mirror.branch_filter.description": "Branches para espelhar. Deixe em branco para espelhar todos os branches. Veja %[2]s documentação sobre a sintaxe. Exemplos: main, release/*" } diff --git a/options/locale_next/locale_pt-PT.json b/options/locale_next/locale_pt-PT.json index 352e948966..4710d3d868 100644 --- a/options/locale_next/locale_pt-PT.json +++ b/options/locale_next/locale_pt-PT.json @@ -83,7 +83,7 @@ "moderation.abuse_category": "Categoria", "moderation.abuse_category.placeholder": "Escolha uma categoria", "moderation.abuse_category.spam": "Spam", - "moderation.abuse_category.malware": "Malware", + "moderation.abuse_category.malware": "Software malicioso", "moderation.abuse_category.illegal_content": "Conteúdo ilegal", "moderation.abuse_category.other_violations": "Outras violações das regras da plataforma", "moderation.report_remarks": "Observações", @@ -109,5 +109,9 @@ "feed.atom.link": "Feed Atom", "keys.ssh.link": "Chaves SSH", "keys.gpg.link": "Chaves GPG", - "repo.diff.commit.previous-short": "Ant." + "repo.diff.commit.previous-short": "Ant.", + "og.repo.summary_card.alt_description": "Cartão de resumo do repositório %[1]s, descrito como: %[2]s", + "repo.settings.push_mirror.branch_filter.label": "Filtro de ramos (opcional)", + "repo.settings.push_mirror.branch_filter.description": "Ramos a serem espelhados. Deixe em branco para espelhar todos os ramos. Veja a %[2]s documentação sobre a sintaxe. Exemplos: main, release/*", + "mail.actions.run_info_sha": "Cometimento: %[1]s" } diff --git a/options/locale_next/locale_ru-RU.json b/options/locale_next/locale_ru-RU.json index 19167d7177..ecd58b8b62 100644 --- a/options/locale_next/locale_ru-RU.json +++ b/options/locale_next/locale_ru-RU.json @@ -23,7 +23,7 @@ "alert.asset_load_failed": "Не удалось получить ресурсы из {path}. Убедитесь, что файлы ресурсов доступны.", "install.invalid_lfs_path": "Не удалось расположить корень LFS по указанному пути: %[1]s", "alert.range_error": " - число должно быть в диапазоне от %[1]s-%[2]s.", - "meta.last_line": "Unskip..", + "meta.last_line": "...ъъ", "mail.actions.not_successful_run_subject": "Провал раб. потока %[1]s в репозитории %[2]s", "mail.actions.successful_run_after_failure_subject": "Возобновление раб. потока %[1]s в репозитории %[2]s", "mail.actions.run_info_trigger": "Причина срабатывания: %[1]s by: %[2]s", @@ -111,5 +111,7 @@ "keys.gpg.link": "Ключи GPG", "profile.edit.link": "Изменить профиль", "og.repo.summary_card.alt_description": "Карточка со сводкой о репозитории %s. Описание: %[2]s", - "mail.actions.run_info_sha": "Коммит: %[1]s" + "mail.actions.run_info_sha": "Коммит: %[1]s", + "repo.settings.push_mirror.branch_filter.description": "Синхронизируемые ветви. Оставьте пустым, чтобы синхронизировать все. Ознакомьтесь с синтаксисом в документации %[2]s. Примеры: main, release/*", + "repo.settings.push_mirror.branch_filter.label": "Выбор ветвей (опционально)" } diff --git a/options/locale_next/locale_uk-UA.json b/options/locale_next/locale_uk-UA.json index 8e99505e57..f014a8dc66 100644 --- a/options/locale_next/locale_uk-UA.json +++ b/options/locale_next/locale_uk-UA.json @@ -111,5 +111,7 @@ "feed.atom.link": "Стрічка Atom", "profile.actions.tooltip": "Більше дій", "og.repo.summary_card.alt_description": "Підсумкова картка репозиторію %[1]s з описом: %[2]s", - "mail.actions.run_info_sha": "Коміт: %[1]s" + "mail.actions.run_info_sha": "Коміт: %[1]s", + "repo.settings.push_mirror.branch_filter.description": "Гілки для дзеркалювання. Залиште порожнім, щоб віддзеркалити всі гілки. Дивіться синтаксис у документації %[2]s. Приклади: main, release/*", + "repo.settings.push_mirror.branch_filter.label": "Фільтр гілок (необов'язково)" } diff --git a/options/locale_next/locale_zh-CN.json b/options/locale_next/locale_zh-CN.json index c235ebd0ad..467c990d3a 100644 --- a/options/locale_next/locale_zh-CN.json +++ b/options/locale_next/locale_zh-CN.json @@ -78,5 +78,8 @@ "repo.diff.commit.previous-short": "上一个", "feed.atom.link": "Atom 订阅源", "profile.edit.link": "编辑个人资料", - "og.repo.summary_card.alt_description": "仓库 %[1]s 的摘要卡片,描述为:%[2]s" + "og.repo.summary_card.alt_description": "仓库 %[1]s 的摘要卡片,描述为:%[2]s", + "repo.settings.push_mirror.branch_filter.label": "分支过滤器(可选)", + "repo.settings.push_mirror.branch_filter.description": "欲镜像的分支。留空以镜像所有分支。关于语法的更多信息,请参见 %[2]s 文档。例如:main, release/*", + "mail.actions.run_info_sha": "提交:%[1]s" } diff --git a/package-lock.json b/package-lock.json index edb57b618a..c41b1f6b7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,7 +56,7 @@ "vue-chartjs": "5.3.1", "vue-loader": "17.4.2", "vue3-calendar-heatmap": "2.0.5", - "webpack": "5.100.0", + "webpack": "5.100.2", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.0" }, @@ -240,9 +240,9 @@ } }, "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.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -525,14 +525,14 @@ } }, "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.4", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.4.tgz", + "integrity": "sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.0.2", + "@emnapi/wasi-threads": "1.0.3", "tslib": "^2.4.0" } }, @@ -548,9 +548,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.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.3.tgz", + "integrity": "sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw==", "dev": true, "license": "MIT", "optional": true, @@ -559,9 +559,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.6.tgz", + "integrity": "sha512-ShbM/3XxwuxjFiuVBHA+d3j5dyac0aEVVq1oluIDf71hUw0aRF59dV/efUsIwFnR6m8JNM2FjZOzmaZ8yG61kw==", "cpu": [ "ppc64" ], @@ -575,9 +575,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.6.tgz", + "integrity": "sha512-S8ToEOVfg++AU/bHwdksHNnyLyVM+eMVAOf6yRKFitnwnbwwPNqKr3srzFRe7nzV69RQKb5DgchIX5pt3L53xg==", "cpu": [ "arm" ], @@ -591,9 +591,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.6.tgz", + "integrity": "sha512-hd5zdUarsK6strW+3Wxi5qWws+rJhCCbMiC9QZyzoxfk5uHRIE8T287giQxzVpEvCwuJ9Qjg6bEjcRJcgfLqoA==", "cpu": [ "arm64" ], @@ -607,9 +607,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.6.tgz", + "integrity": "sha512-0Z7KpHSr3VBIO9A/1wcT3NTy7EB4oNC4upJ5ye3R7taCc2GUdeynSLArnon5G8scPwaU866d3H4BCrE5xLW25A==", "cpu": [ "x64" ], @@ -623,9 +623,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.6.tgz", + "integrity": "sha512-FFCssz3XBavjxcFxKsGy2DYK5VSvJqa6y5HXljKzhRZ87LvEi13brPrf/wdyl/BbpbMKJNOr1Sd0jtW4Ge1pAA==", "cpu": [ "arm64" ], @@ -639,9 +639,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.6.tgz", + "integrity": "sha512-GfXs5kry/TkGM2vKqK2oyiLFygJRqKVhawu3+DOCk7OxLy/6jYkWXhlHwOoTb0WqGnWGAS7sooxbZowy+pK9Yg==", "cpu": [ "x64" ], @@ -655,9 +655,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.6.tgz", + "integrity": "sha512-aoLF2c3OvDn2XDTRvn8hN6DRzVVpDlj2B/F66clWd/FHLiHaG3aVZjxQX2DYphA5y/evbdGvC6Us13tvyt4pWg==", "cpu": [ "arm64" ], @@ -671,9 +671,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.6.tgz", + "integrity": "sha512-2SkqTjTSo2dYi/jzFbU9Plt1vk0+nNg8YC8rOXXea+iA3hfNJWebKYPs3xnOUf9+ZWhKAaxnQNUf2X9LOpeiMQ==", "cpu": [ "x64" ], @@ -687,9 +687,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.6.tgz", + "integrity": "sha512-SZHQlzvqv4Du5PrKE2faN0qlbsaW/3QQfUUc6yO2EjFcA83xnwm91UbEEVx4ApZ9Z5oG8Bxz4qPE+HFwtVcfyw==", "cpu": [ "arm" ], @@ -703,9 +703,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.6.tgz", + "integrity": "sha512-b967hU0gqKd9Drsh/UuAm21Khpoh6mPBSgz8mKRq4P5mVK8bpA+hQzmm/ZwGVULSNBzKdZPQBRT3+WuVavcWsQ==", "cpu": [ "arm64" ], @@ -719,9 +719,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.6.tgz", + "integrity": "sha512-aHWdQ2AAltRkLPOsKdi3xv0mZ8fUGPdlKEjIEhxCPm5yKEThcUjHpWB1idN74lfXGnZ5SULQSgtr5Qos5B0bPw==", "cpu": [ "ia32" ], @@ -735,9 +735,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.6.tgz", + "integrity": "sha512-VgKCsHdXRSQ7E1+QXGdRPlQ/e08bN6WMQb27/TMfV+vPjjTImuT9PmLXupRlC90S1JeNNW5lzkAEO/McKeJ2yg==", "cpu": [ "loong64" ], @@ -751,9 +751,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.6.tgz", + "integrity": "sha512-WViNlpivRKT9/py3kCmkHnn44GkGXVdXfdc4drNmRl15zVQ2+D2uFwdlGh6IuK5AAnGTo2qPB1Djppj+t78rzw==", "cpu": [ "mips64el" ], @@ -767,9 +767,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.6.tgz", + "integrity": "sha512-wyYKZ9NTdmAMb5730I38lBqVu6cKl4ZfYXIs31Baf8aoOtB4xSGi3THmDYt4BTFHk7/EcVixkOV2uZfwU3Q2Jw==", "cpu": [ "ppc64" ], @@ -783,9 +783,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.6.tgz", + "integrity": "sha512-KZh7bAGGcrinEj4qzilJ4hqTY3Dg2U82c8bv+e1xqNqZCrCyc+TL9AUEn5WGKDzm3CfC5RODE/qc96OcbIe33w==", "cpu": [ "riscv64" ], @@ -799,9 +799,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.6.tgz", + "integrity": "sha512-9N1LsTwAuE9oj6lHMyyAM+ucxGiVnEqUdp4v7IaMmrwb06ZTEVCIs3oPPplVsnjPfyjmxwHxHMF8b6vzUVAUGw==", "cpu": [ "s390x" ], @@ -815,9 +815,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.6.tgz", + "integrity": "sha512-A6bJB41b4lKFWRKNrWoP2LHsjVzNiaurf7wyj/XtFNTsnPuxwEBWHLty+ZE0dWBKuSK1fvKgrKaNjBS7qbFKig==", "cpu": [ "x64" ], @@ -831,9 +831,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.6.tgz", + "integrity": "sha512-IjA+DcwoVpjEvyxZddDqBY+uJ2Snc6duLpjmkXm/v4xuS3H+3FkLZlDm9ZsAbF9rsfP3zeA0/ArNDORZgrxR/Q==", "cpu": [ "arm64" ], @@ -847,9 +847,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.6.tgz", + "integrity": "sha512-dUXuZr5WenIDlMHdMkvDc1FAu4xdWixTCRgP7RQLBOkkGgwuuzaGSYcOpW4jFxzpzL1ejb8yF620UxAqnBrR9g==", "cpu": [ "x64" ], @@ -863,9 +863,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.6.tgz", + "integrity": "sha512-l8ZCvXP0tbTJ3iaqdNf3pjaOSd5ex/e6/omLIQCVBLmHTlfXW3zAxQ4fnDmPLOB1x9xrcSi/xtCWFwCZRIaEwg==", "cpu": [ "arm64" ], @@ -879,9 +879,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.6.tgz", + "integrity": "sha512-hKrmDa0aOFOr71KQ/19JC7az1P0GWtCN1t2ahYAf4O007DHZt/dW8ym5+CUdJhQ/qkZmI1HAF8KkJbEFtCL7gw==", "cpu": [ "x64" ], @@ -894,10 +894,26 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.6.tgz", + "integrity": "sha512-+SqBcAWoB1fYKmpWoQP4pGtx+pUUC//RNYhFdbcSA16617cchuryuhOCRpPsjCblKukAckWsV+aQ3UKT/RMPcA==", + "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.6", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.6.tgz", + "integrity": "sha512-dyCGxv1/Br7MiSC42qinGL8KkG4kX0pEsdb0+TKhmJZgCUDBGmyo1/ArCjNGiOLiIAgdbWgmWgib4HoCi5t7kA==", "cpu": [ "x64" ], @@ -911,9 +927,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.6.tgz", + "integrity": "sha512-42QOgcZeZOvXfsCBJF5Afw73t4veOId//XD3i+/9gSkhSV6Gk3VPlWncctI+JcOyERv85FUo7RxuxGy+z8A43Q==", "cpu": [ "arm64" ], @@ -927,9 +943,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.6.tgz", + "integrity": "sha512-4AWhgXmDuYN7rJI6ORB+uU9DHLq/erBbuMoAuB4VWJTu5KtCgcKYPynF0YI1VkBNuEfjNlLrFr9KZPJzrtLkrQ==", "cpu": [ "ia32" ], @@ -943,9 +959,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.6", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.6.tgz", + "integrity": "sha512-NgJPHHbEpLQgDH2MjQu90pzW/5vvXIZ7KOnPyNBm92A6WgZ/7b6fJyUBjoumLqeOQQGqY2QjQxRo97ah4Sj0cA==", "cpu": [ "x64" ], @@ -2032,18 +2048,18 @@ "license": "MIT" }, "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.3.0.tgz", - "integrity": "sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", + "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", "license": "BSD-3-Clause" }, "node_modules/@lit/reactive-element": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.0.tgz", - "integrity": "sha512-L2qyoZSQClcBmq0qajBVbhYEcG6iK0XfLn66ifLe/RfC0/ihpc+pl0Wdn8bJ8o+hj38cG0fGXRgSS20MuXn7qA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", + "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", "license": "BSD-3-Clause", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0" + "@lit-labs/ssr-dom-shim": "^1.4.0" } }, "node_modules/@mcaptcha/core-glue": { @@ -2119,16 +2135,16 @@ } }, "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": { @@ -2286,9 +2302,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.0.tgz", + "integrity": "sha512-2o/FgACbji4tW1dzXOqAV15Eu7DdgbKsF2QKcxfG4xbh5iwU7yr5RRP5/U+0asQliSYv5M4o7BevlGIoSL0LXg==", "cpu": [ "arm" ], @@ -2300,9 +2316,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.0.tgz", + "integrity": "sha512-PSZ0SvMOjEAxwZeTx32eI/j5xSYtDCRxGu5k9zvzoY77xUNssZM+WV6HYBLROpY5CkXsbQjvz40fBb7WPwDqtQ==", "cpu": [ "arm64" ], @@ -2314,9 +2330,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.0.tgz", + "integrity": "sha512-BA4yPIPssPB2aRAWzmqzQ3y2/KotkLyZukVB7j3psK/U3nVJdceo6qr9pLM2xN6iRP/wKfxEbOb1yrlZH6sYZg==", "cpu": [ "arm64" ], @@ -2328,9 +2344,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.0.tgz", + "integrity": "sha512-Pr2o0lvTwsiG4HCr43Zy9xXrHspyMvsvEw4FwKYqhli4FuLE5FjcZzuQ4cfPe0iUFCvSQG6lACI0xj74FDZKRA==", "cpu": [ "x64" ], @@ -2342,9 +2358,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.0.tgz", + "integrity": "sha512-lYE8LkE5h4a/+6VnnLiL14zWMPnx6wNbDG23GcYFpRW1V9hYWHAw9lBZ6ZUIrOaoK7NliF1sdwYGiVmziUF4vA==", "cpu": [ "arm64" ], @@ -2356,9 +2372,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.0.tgz", + "integrity": "sha512-PVQWZK9sbzpvqC9Q0GlehNNSVHR+4m7+wET+7FgSnKG3ci5nAMgGmr9mGBXzAuE5SvguCKJ6mHL6vq1JaJ/gvw==", "cpu": [ "x64" ], @@ -2370,9 +2386,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.0.tgz", + "integrity": "sha512-hLrmRl53prCcD+YXTfNvXd776HTxNh8wPAMllusQ+amcQmtgo3V5i/nkhPN6FakW+QVLoUUr2AsbtIRPFU3xIA==", "cpu": [ "arm" ], @@ -2384,9 +2400,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.0.tgz", + "integrity": "sha512-XBKGSYcrkdiRRjl+8XvrUR3AosXU0NvF7VuqMsm7s5nRy+nt58ZMB19Jdp1RdqewLcaYnpk8zeVs/4MlLZEJxw==", "cpu": [ "arm" ], @@ -2398,9 +2414,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.0.tgz", + "integrity": "sha512-fRvZZPUiBz7NztBE/2QnCS5AtqLVhXmUOPj9IHlfGEXkapgImf4W9+FSkL8cWqoAjozyUzqFmSc4zh2ooaeF6g==", "cpu": [ "arm64" ], @@ -2412,9 +2428,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.0.tgz", + "integrity": "sha512-Btv2WRZOcUGi8XU80XwIvzTg4U6+l6D0V6sZTrZx214nrwxw5nAi8hysaXj/mctyClWgesyuxbeLylCBNauimg==", "cpu": [ "arm64" ], @@ -2426,9 +2442,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.0.tgz", + "integrity": "sha512-Li0emNnwtUZdLwHjQPBxn4VWztcrw/h7mgLyHiEI5Z0MhpeFGlzaiBHpSNVOMB/xucjXTTcO+dhv469Djr16KA==", "cpu": [ "loong64" ], @@ -2440,9 +2456,9 @@ ] }, "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==", + "version": "4.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.0.tgz", + "integrity": "sha512-sB8+pfkYx2kvpDCfd63d5ScYT0Fz1LO6jIb2zLZvmK9ob2D8DeVqrmBDE0iDK8KlBVmsTNzrjr3G1xV4eUZhSw==", "cpu": [ "ppc64" ], @@ -2454,9 +2470,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.0.tgz", + "integrity": "sha512-5GQ6PFhh7E6jQm70p1aW05G2cap5zMOvO0se5JMecHeAdj5ZhWEHbJ4hiKpfi1nnnEdTauDXxPgXae/mqjow9w==", "cpu": [ "riscv64" ], @@ -2468,9 +2484,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.0.tgz", + "integrity": "sha512-N/euLsBd1rekWcuduakTo/dJw6U6sBP3eUq+RXM9RNfPuWTvG2w/WObDkIvJ2KChy6oxZmOSC08Ak2OJA0UiAA==", "cpu": [ "riscv64" ], @@ -2482,9 +2498,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.0.tgz", + "integrity": "sha512-2l9sA7d7QdikL0xQwNMO3xURBUNEWyHVHfAsHsUdq+E/pgLTUcCE+gih5PCdmyHmfTDeXUWVhqL0WZzg0nua3g==", "cpu": [ "s390x" ], @@ -2496,9 +2512,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.0.tgz", + "integrity": "sha512-XZdD3fEEQcwG2KrJDdEQu7NrHonPxxaV0/w2HpvINBdcqebz1aL+0vM2WFJq4DeiAVT6F5SUQas65HY5JDqoPw==", "cpu": [ "x64" ], @@ -2510,9 +2526,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.0.tgz", + "integrity": "sha512-7ayfgvtmmWgKWBkCGg5+xTQ0r5V1owVm67zTrsEY1008L5ro7mCyGYORomARt/OquB9KY7LpxVBZes+oSniAAQ==", "cpu": [ "x64" ], @@ -2524,9 +2540,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.0.tgz", + "integrity": "sha512-B+IJgcBnE2bm93jEW5kHisqvPITs4ddLOROAcOc/diBgrEiQJJ6Qcjby75rFSmH5eMGrqJryUgJDhrfj942apQ==", "cpu": [ "arm64" ], @@ -2538,9 +2554,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.0.tgz", + "integrity": "sha512-+CXwwG66g0/FpWOnP/v1HnrGVSOygK/osUbu3wPRy8ECXjoYKjRAyfxYpDQOfghC5qPJYLPH0oN4MCOjwgdMug==", "cpu": [ "ia32" ], @@ -2552,9 +2568,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.45.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.0.tgz", + "integrity": "sha512-SRf1cytG7wqcHVLrBc9VtPK4pU5wxiB/lNIkNmW2ApKXIg+RpqwHfsaEK+e7eH4A1BpI6BX/aBWXxZCIrJg3uA==", "cpu": [ "x64" ], @@ -3136,9 +3152,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, @@ -3517,9 +3533,9 @@ "license": "MIT" }, "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.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.7.tgz", + "integrity": "sha512-1GM9z6BJOv86qkPvzh2i6VW5+VVrXxCLknfmTkWEqz+6DqosiY28XUWCTmBcJ0ACzKqx/iwdIREfo1fwExIlkA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -3833,9 +3849,9 @@ } }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.0.tgz", - "integrity": "sha512-LRw5BW29sYj9NsQC6QoqeLVQhEa+BwVINYyMlcve+6stwdBsSt5UB7zw4UZB4+4PNqIVilHoMaPWCb/KhABHQw==", + "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" ], @@ -3847,9 +3863,9 @@ ] }, "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.0.tgz", - "integrity": "sha512-zYX8D2zcWCAHqghA8tPjbp7LwjVXbIZP++mpU/Mrf5jUVlk3BWIxkeB8yYzZi5GpFSlqMcRZQxQqbMI0c2lASQ==", + "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" ], @@ -3861,9 +3877,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.0.tgz", - "integrity": "sha512-YsYOT049hevAY/lTYD77GhRs885EXPeAfExG5KenqMJ417nYLS2N/kpRpYbABhFZBVQn+2uRPasTe4ypmYoo3w==", + "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" ], @@ -3875,9 +3891,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.0.tgz", - "integrity": "sha512-PSjvk3OZf1aZImdGY5xj9ClFG3bC4gnSSYWrt+id0UAv+GwwVldhpMFjAga8SpMo2T1GjV9UKwM+QCsQCQmtdA==", + "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" ], @@ -3889,9 +3905,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.0.tgz", - "integrity": "sha512-KC/iFaEN/wsTVYnHClyHh5RSYA9PpuGfqkFua45r4sweXpC0KHZ+BYY7ikfcGPt5w1lMpR1gneFzuqWLQxsRKg==", + "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" ], @@ -3903,9 +3919,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.0.tgz", - "integrity": "sha512-CDh/0v8uot43cB4yKtDL9CVY8pbPnMV0dHyQCE4lFz6PW/+9tS0i9eqP5a91PAqEBVMqH1ycu+k8rP6wQU846w==", + "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" ], @@ -3917,9 +3933,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.0.tgz", - "integrity": "sha512-+TE7epATDSnvwr3L/hNHX3wQ8KQYB+jSDTdywycg3qDqvavRP8/HX9qdq/rMcnaRDn4EOtallb3vL/5wCWGCkw==", + "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" ], @@ -3931,9 +3947,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.0.tgz", - "integrity": "sha512-VBAYGg3VahofpQ+L4k/ZO8TSICIbUKKTaMYOWHWfuYBFqPbSkArZZLezw3xd27fQkxX4BaLGb/RKnW0dH9Y/UA==", + "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" ], @@ -3945,9 +3961,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.0.tgz", - "integrity": "sha512-9IgGFUUb02J1hqdRAHXpZHIeUHRrbnGo6vrRbz0fREH7g+rzQy53/IBSyadZ/LG5iqMxukriNPu4hEMUn+uWEg==", + "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" ], @@ -3959,9 +3975,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.0.tgz", - "integrity": "sha512-LR4iQ/LPjMfivpL2bQ9kmm3UnTas3U+umcCnq/CV7HAkukVdHxrDD1wwx74MIWbbgzQTLPYY7Ur2MnnvkYJCBQ==", + "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" ], @@ -3973,9 +3989,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.0.tgz", - "integrity": "sha512-HCupFQwMrRhrOg7YHrobbB5ADg0Q8RNiuefqMHVsdhEy9lLyXm/CxsCXeLJdrg27NAPsCaMDtdlm8Z2X8x91Tg==", + "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" ], @@ -3987,9 +4003,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.0.tgz", - "integrity": "sha512-Ckxy76A5xgjWa4FNrzcKul5qFMWgP5JSQ5YKd0XakmWOddPLSkQT+uAvUpQNnFGNbgKzv90DyQlxPDYPQ4nd6A==", + "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" ], @@ -4001,9 +4017,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.0.tgz", - "integrity": "sha512-HfO0PUCCRte2pMJmVyxPI+eqT7KuV3Fnvn2RPvMe5mOzb2BJKf4/Vth8sSt9cerQboMaTVpbxyYjjLBWIuI5BQ==", + "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" ], @@ -4015,9 +4031,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.0.tgz", - "integrity": "sha512-9PZdjP7tLOEjpXHS6+B/RNqtfVUyDEmaViPOuSqcbomLdkJnalt5RKQ1tr2m16+qAufV0aDkfhXtoO7DQos/jg==", + "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" ], @@ -4029,9 +4045,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.0.tgz", - "integrity": "sha512-qkE99ieiSKMnFJY/EfyGKVtNra52/k+lVF/PbO4EL5nU6AdvG4XhtJ+WHojAJP7ID9BNIra/yd75EHndewNRfA==", + "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" ], @@ -4043,9 +4059,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.0.tgz", - "integrity": "sha512-MjXek8UL9tIX34gymvQLecz2hMaQzOlaqYJJBomwm1gsvK2F7hF+YqJJ2tRyBDTv9EZJGMt4KlKkSD/gZWCOiw==", + "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" ], @@ -4060,9 +4076,9 @@ } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.0.tgz", - "integrity": "sha512-9LT6zIGO7CHybiQSh7DnQGwFMZvVr0kUjah6qQfkH2ghucxPV6e71sUXJdSM4Ba0MaGE6DC/NwWf7mJmc3DAng==", + "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" ], @@ -4074,9 +4090,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.0.tgz", - "integrity": "sha512-HYchBYOZ7WN266VjoGm20xFv5EonG/ODURRgwl9EZT7Bq1nLEs6VKJddzfFdXEAho0wfFlt8L/xIiE29Pmy1RA==", + "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" ], @@ -4088,9 +4104,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.0.tgz", - "integrity": "sha512-+oLKLHw3I1UQo4MeHfoLYF+e6YBa8p5vYUw3Rgt7IDzCs+57vIZqQlIo62NDpYM0VG6BjWOwnzBczMvbtH8hag==", + "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" ], @@ -5389,9 +5405,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": { @@ -5402,7 +5418,7 @@ "pathval": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/chalk": { @@ -5797,13 +5813,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", @@ -6015,9 +6031,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.32.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.1.tgz", + "integrity": "sha512-dbeqFTLYEwlFg7UGtcZhCCG/2WayX72zK3Sq323CEX29CY81tYfVhw1MIdduCtpstB0cTOhJswWlM/OEB3Xp+Q==", "license": "MIT", "engines": { "node": ">=0.10" @@ -6939,9 +6955,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.182", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz", + "integrity": "sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -7193,9 +7209,9 @@ } }, "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.6", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.6.tgz", + "integrity": "sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -7205,31 +7221,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.6", + "@esbuild/android-arm": "0.25.6", + "@esbuild/android-arm64": "0.25.6", + "@esbuild/android-x64": "0.25.6", + "@esbuild/darwin-arm64": "0.25.6", + "@esbuild/darwin-x64": "0.25.6", + "@esbuild/freebsd-arm64": "0.25.6", + "@esbuild/freebsd-x64": "0.25.6", + "@esbuild/linux-arm": "0.25.6", + "@esbuild/linux-arm64": "0.25.6", + "@esbuild/linux-ia32": "0.25.6", + "@esbuild/linux-loong64": "0.25.6", + "@esbuild/linux-mips64el": "0.25.6", + "@esbuild/linux-ppc64": "0.25.6", + "@esbuild/linux-riscv64": "0.25.6", + "@esbuild/linux-s390x": "0.25.6", + "@esbuild/linux-x64": "0.25.6", + "@esbuild/netbsd-arm64": "0.25.6", + "@esbuild/netbsd-x64": "0.25.6", + "@esbuild/openbsd-arm64": "0.25.6", + "@esbuild/openbsd-x64": "0.25.6", + "@esbuild/openharmony-arm64": "0.25.6", + "@esbuild/sunos-x64": "0.25.6", + "@esbuild/win32-arm64": "0.25.6", + "@esbuild/win32-ia32": "0.25.6", + "@esbuild/win32-x64": "0.25.6" } }, "node_modules/esbuild-loader": { @@ -10147,9 +10164,9 @@ } }, "node_modules/lit": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz", - "integrity": "sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.1.tgz", + "integrity": "sha512-Ksr/8L3PTapbdXJCk+EJVB78jDodUMaP54gD24W186zGRARvwrsPfS60wae/SSCTCNZVPd1chXqio1qHQmu4NA==", "license": "BSD-3-Clause", "dependencies": { "@lit/reactive-element": "^2.1.0", @@ -10158,20 +10175,20 @@ } }, "node_modules/lit-element": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.0.tgz", - "integrity": "sha512-MGrXJVAI5x+Bfth/pU9Kst1iWID6GHDLEzFEnyULB/sFiRLgkd8NPK/PeeXxktA3T6EIIaq8U3KcbTU5XFcP2Q==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz", + "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==", "license": "BSD-3-Clause", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit-labs/ssr-dom-shim": "^1.4.0", "@lit/reactive-element": "^2.1.0", "lit-html": "^3.3.0" } }, "node_modules/lit-html": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.0.tgz", - "integrity": "sha512-RHoswrFAxY2d8Cf2mm4OZ1DgzCoBKUKSPvA1fhtSELxUERq2aQQ2h05pO9j81gS1o7RIRJ+CePLogfyahwmynw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz", + "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==", "license": "BSD-3-Clause", "dependencies": { "@types/trusted-types": "^2.0.2" @@ -15002,9 +15019,9 @@ } }, "node_modules/unrs-resolver": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.0.tgz", - "integrity": "sha512-uw3hCGO/RdAEAb4zgJ3C/v6KIAFFOtBoxR86b2Ejc5TnH7HrhTWJR2o0A9ullC3eWMegKQCw/arQ/JivywQzkg==", + "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", @@ -15015,25 +15032,25 @@ "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.0", - "@unrs/resolver-binding-android-arm64": "1.11.0", - "@unrs/resolver-binding-darwin-arm64": "1.11.0", - "@unrs/resolver-binding-darwin-x64": "1.11.0", - "@unrs/resolver-binding-freebsd-x64": "1.11.0", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.0", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.0", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.0", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.0", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.0", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.0", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.0", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.0", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.0", - "@unrs/resolver-binding-linux-x64-musl": "1.11.0", - "@unrs/resolver-binding-wasm32-wasi": "1.11.0", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.0", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.0", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.0" + "@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": { @@ -15140,9 +15157,9 @@ "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.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.4.tgz", + "integrity": "sha512-SkaSguuS7nnmV7mfJ8l81JGBFV7Gvzp8IzgE8A8t23+AxuNX61Q5H1Tpz5efduSN7NHC8nQXD3sKQKZAu5mNEA==", "dev": true, "license": "MIT", "dependencies": { @@ -15324,9 +15341,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.45.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.0.tgz", + "integrity": "sha512-WLjEcJRIo7i3WDDgOIJqVI2d+lAC3EwvOGy+Xfq6hs+GQuAA4Di/H72xmXkOhrIWFg2PFYSKZYfH0f4vfKXN4A==", "dev": true, "license": "MIT", "dependencies": { @@ -15340,26 +15357,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.45.0", + "@rollup/rollup-android-arm64": "4.45.0", + "@rollup/rollup-darwin-arm64": "4.45.0", + "@rollup/rollup-darwin-x64": "4.45.0", + "@rollup/rollup-freebsd-arm64": "4.45.0", + "@rollup/rollup-freebsd-x64": "4.45.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.45.0", + "@rollup/rollup-linux-arm-musleabihf": "4.45.0", + "@rollup/rollup-linux-arm64-gnu": "4.45.0", + "@rollup/rollup-linux-arm64-musl": "4.45.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.45.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.45.0", + "@rollup/rollup-linux-riscv64-gnu": "4.45.0", + "@rollup/rollup-linux-riscv64-musl": "4.45.0", + "@rollup/rollup-linux-s390x-gnu": "4.45.0", + "@rollup/rollup-linux-x64-gnu": "4.45.0", + "@rollup/rollup-linux-x64-musl": "4.45.0", + "@rollup/rollup-win32-arm64-msvc": "4.45.0", + "@rollup/rollup-win32-ia32-msvc": "4.45.0", + "@rollup/rollup-win32-x64-msvc": "4.45.0", "fsevents": "~2.3.2" } }, @@ -15633,9 +15650,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.100.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.0.tgz", - "integrity": "sha512-H8yBSBTk+BqxrINJnnRzaxU94SVP2bjd7WmA+PfCphoIdDpeQMJ77pq9/4I7xjLq38cB1bNKfzYPZu8pB3zKtg==", + "version": "5.100.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.2.tgz", + "integrity": "sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==", "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", diff --git a/package.json b/package.json index c154270c6c..f6e998a570 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "vue-chartjs": "5.3.1", "vue-loader": "17.4.2", "vue3-calendar-heatmap": "2.0.5", - "webpack": "5.100.0", + "webpack": "5.100.2", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.0" }, diff --git a/release-notes-published/12.0.0.md b/release-notes-published/12.0.0.md index e69de29bb2..6d83eef3c5 100644 --- a/release-notes-published/12.0.0.md +++ b/release-notes-published/12.0.0.md @@ -0,0 +1,476 @@ + + + + +## Release notes + +- Breaking security features + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7924): remove API authentication methods that uses the URL query. They are disabled by default and this only has an impact if `[security].DISABLE_QUERY_AUTH_TOKEN=false` is explicitly set. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#removing-deprecated-api-authentication-methods). +- Security features + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7829): relax email requirements. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#relaxing-the-requirements-on-email-addresses). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7693): consider WebAuthn & SSH for instance signing. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6897): add SSH signing support for instances. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#instance-signing-with-ssh). +- Breaking features + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8035): The `forgejo docs` command is deprecated and CLI errors are now displayed on stderr instead of stdout. These breaking changes happened because the package used to parse the command line arguments was [upgraded from v2 to v3](https://cli.urfave.org/migrate-v2-to-v3/). A [separate project was initiated](https://github.com/urfave/cli-docs) to re-implement the `docs` command, but it is not yet production ready. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7745): remove the legacy `TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY` setting +- Breaking bug fixes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8139): fail if `sha` is not provided to the `POST /repos/{owner}/{repo}/contents` API endpoint. Although it was documented to be required, it was not enforced and clients that do not set the `sha` will no longer succeed. +- User Interface features + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8185): transform fediverse handles (ex. @forgejo@floss.social and !forgejo@programming.dev) into links to https://fedirect.toolforge.org. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#redirecting-fediverse-handles). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8121): add user visibility description in the settings page. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8111): add model viewer for `.glb` (GLTF) model in file view. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#gltf-viewer). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7998): show size constraints of custom avatar. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7992): add links to milestones and projects in issue comments. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7958): global styling for the kbd tag. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7947): hints in empty usercards lists. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7906): the user profile has been redesigned. The most notable change is that actions have been moved to a dropdown and several new actions were added. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7531): improve the description in the packages settings. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7516): inline public ssh key in verification command. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7481): use switch element for markdown editor modes. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7388): make JS asset load error message translatable. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7385): improve performances by using `git switch -c` instead of `git checkout -b`. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7377): clarify the desired autocompletion type for the clone address in migrations. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7373): improve the clarity of the migration description textarea. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7361): automatically refresh workflows in the "Actions" list. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#automatically-refreshing-workflows). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7274): improve error pages. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7155): improve the user experience to review individual commits in a pull request. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#improved-ux-for-per-commit-reviews). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7128): use the available screen width when displaying Forgejo Actions logs. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6933): show if a commit is verified in the activity feed of a user or an organization. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6813): reimplemented editor Tab key handling with accessibility safeguards. Balance having the editor work as expected by developers (with Tab key affecting indentation) while also not impeding keyboard navigation. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#tabs-indentations-in-the-comment-editor) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6795): redesign the migration selection page. +- User Interface bug fixes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8417) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8514)): multiple ComboMarkdownEditors on one page interfere with each other. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7749) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8362)): pasting images into the comment editor will now show that image in the ‘dropzone’. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8296) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8317)): add missing trust status to pull review commits. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8246) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8282)): add missing lazy load attribute to images. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8067): retain sort type when viewing issue or pull requests. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7893): include enough activity for the entire heatmap. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7726): show warning in locked issue discussion. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7492): ensure consistent switch position in the markdown editor. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7420): display user-friendly message for range error. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7402): make limits clearer in the create repository form. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7307): don't put trailing slash in autogenerated name in the migration form. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7245): allow user with actions write permission to run a workflow from the web UI. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6799): ensure usercards in grid have the same width. +- Localization + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8238) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8294)): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8178): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8077): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7969): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7895): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7819): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7742): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7637): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7572): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7507): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7438): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7363): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7275): i18n: update of translations from Codeberg Translate +- Features + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8179): new `GET /repos/{owner}/{repo}/git/blobs` API endpoint to retrieve multiple blobs at once. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8177): always publish the link to the commit status. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8143): improve the performances of the generation of bundled assets. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8115): enable `mlkem768x25519-sha256` by default for builtin ssh. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8070): support artifact uploads for OCI container packages. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8047): add `admin user reset-mfa` CLI command. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7988): update the list of ambigious characters. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7986): make Forgejo Actions server logs less noisy. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7968): allow searching issues by number, prioritize title matches when sorted by relevance. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7953): replace go-rpmutils library with our own. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#forgejo-build-time-optimization). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7902): configurable default units for mirrors. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7896): a repository administrator has control over reindexing the issues. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7803): auto cleanup of offline runners. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7727): improved performances when checking for conflicts on pull requests. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#faster-conflict-checking). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7716): allow access to publicly available `/api/v1/packages/{username}` without a token. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7699): implement the `GET /repos/{owner}/{repo}/actions/runs` and `GET /repos/{owner}/{repo}/actions/runs/{run_id}` API endpoints. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7527): use git-replay for rebasing for better performances. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7509): send mail on failed or recovered Forgejo Actions run. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#forgejo-actions-email-notifications-on-failure). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7508): Forgejo Actions failure, success, recover webhooks. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7418): add `last_commit_when` to API contents responses. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7387): include a default robots.txt to reduce the impact of crawlers. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#default-robotstxt). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7212): use XORM EngineGroup instead of single Engine connection. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#xorm-enginegroup-connections-for-optimized-database-query-routing-and-load-balancing). + - [PR](https://codeberg.org/forgejo/forgejo/pulls/2364): sync forks. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#keeping-forks-in-sync). +- Bug fixes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8511) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8516)): pull requests were not blocked by review request for a whitelisted team. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8475) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8480)): several fixes of the ALT RPM package registry. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8391) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8459)): allow lowercase as well as uppercase token keyword in the auth header. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8450) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8454)): correctly mark reviews as stale for AGit pull requests. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8367) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8386)): user activation failed when an email address contained uppercase letters. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8330) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8349)): fix: load OldMilestone based on OldMilestoneID, not MilestoneID + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8037): omit Content-Length on 307 redirects when serving direct manifest for containers. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8034): fix a bug causing the PASCAL-modifier to return camel-case. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8028): remove the trailing slash from the issuer in OAuth claims. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8025): return the correct AGit type in ssh_info. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7932): fix url validation in the webhook add/edit API. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7930): add error reporting to pull requests with invalid Forgejo Actions workflow files. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7644): allow instance API URLs in release assets. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7604): improve the dashboard loading performances. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7454): fix a border case where it was not possible to cancel a pull request review. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7409): fix acme renewal. + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6352): migrate Maven packages to "groupId:artifactId" name concatenation, regenerate metadata and fix missing groupId. +- Included for completeness but not worth a release note + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8534): i18n: update of translations from Codeberg Translate + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8530) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8532)): fix(packages): skip another stack frame from logging + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8527) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8528)): fix: ignore "Close" error when uploading container blob + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8524) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8526)): chore: failed authentication attempts are not errors and are displayed at the log info level + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8519) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8523)): fix: expanding exactly 20 lines between diff sections leaves visual artifact + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8301) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8518)): chore: use eventually for mysql collation test + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8492) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8498)): fix(code-search): HighlightSearchResultCode should count the number of bytes and not the number of runes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8464) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8474)): fix: use parent context for new transactions + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8460) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8466)): chore: disable mismatched root URL e2e test for safari + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8461) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8463)): chore: do not navigate to same URL in E2E test + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8448) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8455)): fix(email): actions notification template confuses branch with PR + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8258) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8439)): fix: corrupted wiki unit default permission (#8234 follow-up) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8366) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8404)): fix: cancelled or skipped runs are not failures for notifications + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8400) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8402)): chore: improve reliability of webauthn e2e test + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8261) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8398)): fix: skip empty tokens in SearchOptions.Tokens() + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8374) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8390)): fix: disable Forgejo Actions email notifications on recovery + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8326) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8331)): fix: make API /repos/{owner}/{repo}/compare/{basehead} work with forks + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8320) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8321)): chore: sort blocked users list for determistic results + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8267) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8319)): fix: abuse reports string data types + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8304) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8318)): fix: pass doer's ID for CRUD instance signing + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8002) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8290)): fix(ui): release: name is overridden with tag name on edit + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8286) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8288)): Revert "fix(api): document `is_system_webhook` field (#7784)" + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8271) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8277)): CI debug: testSleep: show actual times on failures + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8268): chore: update security option in issue templates + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8260): Token.ParseIssueReference crashing on empty string + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8256): Update renovate to v41.1.4 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8253): Update renovate to v41 (forgejo) (major) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8252): add an index to the ActionRun.stopped column + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8250): bug: unify RepoActionRun and ActionRun structs + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8248): Update module github.com/go-chi/chi/v5 to v5.2.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8245): Downgrade playwright temporarily and allow running all e2e tests + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8243): git/blob use NewTruncatedReader for profile and codeowners + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8242): bug: Forgejo Actions email notifications are opt-in + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8236): prevent 500 message on invalid username + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8227): only send Forgejo Actions notifications to one user + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8226): chore: sort mailer messages in test assertion + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8224): chore(release-notes): Forgejo v11.0.2 + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8223): blob: GetBlobContent: reduce allocations + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8220): fix(tests): TestInitInstructions must use forEachObjectFormat + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8219): Update module code.forgejo.org/forgejo/act to v1.28.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8218): Update data.forgejo.org/oci/alpine Docker tag to v3.22 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8217): Update module github.com/minio/minio-go/v7 to v7.0.94 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8216): chore: migrate to `@stylistic/eslint-plugin` + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8215): Update dependency eslint-plugin-wc to v3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8214): fix(ui): issue comment anchor on time stamp + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8209): git_model.CommitStatusesHideActionsURL is obsolete + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8207): Remove 1ms delay before inserting list prefix, fix race condition in tests + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8205): chore: remove gopls in Makefile + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8202): do not check for `object_format_name` field + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8199): feat(ui): use kbd in label selector hint, remove enter + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8198): [gitea] week 2025-22 cherry pick (gitea/main -> forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8197): Fix sentence structure mentioning cooldown period + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8195): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8194): Update renovate to v40.57.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8190): Update dependency chart.js to v4.5.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8188): make test suite run on older git version + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8186): Update module github.com/go-sql-driver/mysql to v1.9.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8183): Update environment-to-ini README + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8181): Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.3.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8176): Dockerfile should re-use bindata files when possible + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8174): Update dependency minimatch to v10.0.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8172): use zstd.WithLowerEncoderMem for generate-bindata + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8168): do not mix urfave v2 with urfave v3 + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8166): chore(ci): skip tests if TEST_{MINIO_ENDPOINT,ELASTICSEARCH_URL} is not set + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8163): Update module gitlab.com/gitlab-org/api/client-go to v0.130.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8162): Update module github.com/minio/minio-go/v7 to v7.0.93 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8160): Update dependency postcss to v8.5.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8159): Update dependency minimatch to v10.0.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8157): chore(ci): use code.forgejo.org/forgejo/migration-test for migration tests + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8150): Update dependency happy-dom to v18 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8149): Update dependency typescript-eslint to v8.34.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8148): Update dependency @playwright/test to v1.53.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8147): Update ghcr.io/devcontainers/features/git-lfs Docker tag to v1.2.4 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8146): Update dependency postcss-nesting to v13.0.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8145): Update dependency @vitest/eslint-plugin to v1.2.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8144): chore: fix tests for old git versions + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8140): chore(ci): run additional tests in integration + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8137): Remove shebang from bash autocompletion + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8134): Make relative-time a self-maintaining custom element + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8129): create shell.nix; update flake.* + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8128): Update module connectrpc.com/connect to v1.18.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8127): Update dependency markdownlint-cli to v0.45.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8126): Update dependency eslint-plugin-regexp to v2.9.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8125): Update vitest monorepo to v3.2.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8118): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8117): Update renovate to v40.48.4 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8112): remove download attribute from external assets + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8108): always render detailed team permissions table in sidebar + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8103): Update x/tools to v0.34.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8102): Update vitest monorepo to v3.2.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8101): Update module github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker to v3.3.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8099): Update linters (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8098): Update dependency happy-dom to v17.6.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8097): Update dependency @vitejs/plugin-vue to v5.2.4 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8096): Update dependency @axe-core/playwright to v4.10.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8094): show membership of limited orgs + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8091): Update module golang.org/x/crypto to v0.39.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8090): Update module github.com/sergi/go-diff to v1.4.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8086): Update dependency go to v1.24.4 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8078): Federated user activity following: Isolated model changes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8066): rename api.{List,}ActionRun to api.{List,}RepoActionRun + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8065): Update module go.uber.org/mock/mockgen to v0.5.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8064): Update module github.com/blevesearch/bleve/v2 to v2.5.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8063): Update dependency vue to v3.5.16 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8062): Update dependency postcss to v8.5.4 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8061): chore: extract commit header template + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8058): chore: drop unused `misspell` + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8056): Update module code.forgejo.org/f3/gof3/v3 to v3.11.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8055): chore(renovate): disable indirect digest updates for stable + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8054): chore: drop unused `@typescript-eslint/parser` package + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8052): Update linters (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8051): Update dependency happy-dom to v17.6.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8050): chore(renovate): bump to v40.40.0 and disable v7 + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8049): CLI is forgejo not Forgejo + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8044): add missing bottom margin for verification-button in release view + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8041): [gitea] Always use an empty line to separate the commit message and trailer + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8040): [gitea] week 2025-21 cherry pick (gitea/main -> forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8038): Add a GNU Guix manifest + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8021): chore(cleanup): suppress non actionable XORM warnings + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8019): migrate repository.topics column for SQLite + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7994): chore(cleanup): replaces unnecessary calls to formatting functions by non-formatting equivalents + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7987): aggregate deleted team as ghost team + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7981): add validating user password as trace region + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7978): chore(cleanup): fix and simplify API comparison helper + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7975): fix(i18n): use correct base capitalization style + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7961): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7959): Update renovate to v40.31.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7954): Update forgejo go-chi packages (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7952): Update module github.com/ProtonMail/go-crypto to v1.3.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7950): fix(ui): relative time elements were reset on htmx swap + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7945): `overflow-wrap` strategy in `.markup` CSS class + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7944): fix(ui): change escaping button bg on selected lines + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7933): do not unconditionally append $(GITEA_COMPATIBILITY) in version + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7925): fix(ui): center footer links + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7922): Update go-openapi packages (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7920): unify repository topics field by replacing JSON null with empty array + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7919): Update dependency webpack to v5.99.9 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7918): Update dependency sharp to v0.34.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7917): chore: QoL improvements to tests + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7914): chore(renovate): disable indirect major updates for stable branches + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7910): Update dependency clippie to v4.1.7 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7908): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7907): Update renovate to v40.26.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7901): Update module github.com/yuin/goldmark to v1.7.12 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7898): chore(ui): cleanup unused color CSS + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7894): fix(ui): fix force-push compare line layout + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7890): Update module github.com/alecthomas/chroma/v2 to v2.18.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7884): parse `change-id` in the git commit header + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7881): Update module github.com/blevesearch/bleve/v2 to v2.5.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7879): Update dependency vue to v3.5.14 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7877): Migrate renovate config + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7872): fix(ui): disable autocapitalization/autocorrect for username inputs + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7868): fix(ui): disable spellcheck on TOTP form fields + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7866): chore: remove unused update-locales.sh + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7857): Update module github.com/msteinert/pam/v2 to v2.1.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7856): Update module code.forgejo.org/forgejo/act to v1.26.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7852): Fix TestSSHPushMirror/Normal/Check_mirrored_content test + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7849): Update github.com/golang-jwt/jwt/v4 (indirect) to v4.5.2 [SECURITY] (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7848): ci(renovate): only fail on error + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7847): Update module github.com/niklasfasching/go-org to v1.8.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7840): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7835): remove redundant permission check in RemoveLabel + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7833): test(ui-e2e): fix flaky repo wiki test + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7830): Update module github.com/go-webauthn/webauthn to v0.13.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7822): chore(ui): clean up hashbox CSS, small design changes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7817): replace ß with ss in normalizeUserName + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7814): Update dependency globals to v16.1.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7809): Update module golang.org/x/oauth2 to v0.30.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7807): Update dependency go to v1.24.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7799): add missing loadbalancing policies for EngineGroup connections + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7798): Update module golang.org/x/net to v0.40.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7797): Update module golang.org/x/image to v0.27.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7792): [skip ci] chore: remove backport script + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7789): Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.6 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7785): [SKIP CI] chore: update CODEOWNERS + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7784): fix(api): document `is_system_webhook` field + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7778): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7777): Update renovate to v40 (forgejo) (major) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7776): Update renovate to v39.264.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7773): remove artificial delay for PR update + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7772): chore: Fix outdated usage of unittest.OverrideFixtures + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7770): Update module github.com/42wim/httpsig to v1.2.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7769): Update dependency @github/relative-time-element to v4.4.6 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7768): Update github.com/42wim/sshsig digest to 5100632 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7765): chore(release-notes): Forgejo v7.0.15 + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7764): chore(release-notes): Forgejo v11.0.1 + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7762): document that /repos/{owner}/{repo}/pulls may contain nulls + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7760): Update dependency forgejo/release-notes-assistant to v1.2.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7759): chore(renovate): use `gitea-releases` datasource for rna + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7758): chore(renovate): allow updating release notes assistant + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7746): fix(ui): improve force-push compare line layout + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7744): Update dependency eslint-plugin-unicorn to v59 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7740): fix(ui): multiple fixes of sync fork UI + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7739): Update module github.com/redis/go-redis/v9 to v9.8.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7738): Update module github.com/alecthomas/chroma/v2 to v2.17.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7736): Update linters (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7735): Update dependency happy-dom to v17.4.6 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7732): ci: add clarification regarding test label + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7731): chore: fix test to avoid data race + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7728): refactor & enhance AP elements used + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7720): chore(release): next-digest moved to invisible.forgejo.org + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7715): chore: replace `github.com/go-testfixtures/testfixtures` + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7714): enhance validateable interface + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7713): [gitea] week 2025-17 cherry pick (gitea/main -> forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7707): do not set GOPROXY=direct in Dockerfile* + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7705): chore(ui): remove unused fomantic font size classes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7697): better comments and variable names for ActionRunNowDone + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7696): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7695): Update renovate to v39.261.4 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7690): fix various typos + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7689): Update module github.com/yuin/goldmark to v1.7.11 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7687): chore: tune down remote user promotion debug message shown as error + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7685): use `linguist-generated` for language stats + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7683): set default restricted for OAuth2 user + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7682): chore: simplify `GetDiff` + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7680): chore: remove unused linters + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7678): add label for avatar settings + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7667): i18n(en): fix typo in archive notice + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7665): Update linters (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7663): Update dependency @playwright/test to v1.52.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7662): Update module github.com/PuerkitoBio/goquery to v1.10.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7661): Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7659): Update dependency webpack to v5.99.7 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7648): chore: merge tests.AddFixtures and unittest.OverrideFixtures + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7640): Remove "create branch" button on mirrored repos + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7616): fix(ui): make pagination labels always visible to screenreader + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7613): Update module mvdan.cc/gofumpt to v0.8.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7612): Update linters (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7611): Update vitest monorepo to v3.1.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7610): Update dependency @vitest/eslint-plugin to v1.1.43 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7607): Update module github.com/alecthomas/chroma/v2 to v2.17.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7606): Update module github.com/minio/minio-go/v7 to v7.0.91 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7602): [gitea] week 2025-16 cherry pick (gitea/main -> forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7597): delay-write trace.dat for forgejo diagnosis + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7588): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7587): Update renovate to v39.252.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7580): feat(ui): enlarge metadata line gaps in issue list and refactor + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7579): i18n(en): add positional hints to sync_fork placeholders + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7578): fix(ui): overflow tabular menu CSS fixes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7577): feat(ui): make fork related banners more consistent + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7575): fix(ui): use correct branch name in branch tag selector + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7573): Update dependency webpack to v5.99.6 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7571): fix(ui): show commit icon in branch dropdown button when viewing a commit + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7565): grammar in a release API error message + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7561): Update module github.com/caddyserver/certmagic to v0.23.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7560): Update module github.com/mattn/go-sqlite3 to v1.14.28 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7558): fix(ui): make tag dropdown clickable again + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7557): Update dependency python to v3.13.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7555): chore(release): v10.0 is EOL [skip ci] + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7554): chore(renovate): fix package name matching for go majors [skip ci] + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7552): Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7551): Update https://data.forgejo.org/actions/git-backporting action to v4.8.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7550): Update dependency chart.js to v4.4.9 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7545): Update Node.js to v22 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7543): match PackageBlob.HashBlake2b definition and migration + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7539): fix(UI): i18n: improve naming + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7538): [gitea] week 2025-15 cherry pick (gitea/main -> forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7534): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7532): Update renovate to v39.240.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7528): Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7520): package_blob.has_blake2b may be null + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7512): chore: use `sharp` to generate images + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7510): chore: refactor for Actions Done Notification + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7505): Update module golang.org/x/tools/cmd/deadcode to v0.32.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7504): Update module golang.org/x/net to v0.39.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7503): Update dependency katex to v0.16.22 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7499): chore(i18n): update contributing documentation with JSON format + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7497): Update module golang.org/x/image to v0.26.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7495): Update module github.com/minio/minio-go/v7 to v7.0.90 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7494): Update dependency webpack to v5.99.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7491): Actions Done Notification + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7490): Update dependency webpack to v5.99.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7488): Update module go.uber.org/mock to v0.5.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7486): [gitea] week 2025-14 cherry pick (gitea/main -> forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7485): Update module golang.org/x/crypto to v0.37.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7484): Update renovate to v39.233.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7479): Minor grammatical fix to runner deletion message + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7475): Update module golang.org/x/oauth2 to v0.29.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7473): Update module github.com/fsnotify/fsnotify to v1.9.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7472): Update dependency clippie to v4.1.6 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7471): fix(ui): ensure dimmer always covers whole page + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7470): fix(ui): only run auth_name code on new and edit page + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7469): chore(release-notes): Forgejo v11.0.0 + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7468): Update module github.com/blevesearch/bleve/v2 to v2.5.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7467): Update dependency typescript to v5.8.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7465): Update dependency ansi_up to v6.0.5 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7463): chore: always enable webpack progress + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7462): chore(i18n): add a meta line to the base json translation + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7459): Update module github.com/alecthomas/chroma/v2 to v2.16.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7458): Update module code.gitea.io/sdk/gitea to v0.21.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7456): Update dependency ansi_up to v6.0.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7455): Makefile & BSDmakefile changes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7453): chore(sec): unify usage of `crypto/rand.Read` + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7452): make installing Forgejo work again + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7451): chore(i18n): cleanup `settings.adopt` string + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7434): Update module github.com/mattn/go-sqlite3 to v1.14.27 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7433): feat(build): run lint-locale-usage w/o --allow-missing-msgids + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7431): make repo clone https/ssh listener conditional + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7429): feat(build): uniform ini parsing + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7425): feat(locale Iter): properly support trPluralString + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7424): Update module github.com/mattn/go-sqlite3 to v1.14.25 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7423): Update module github.com/go-webauthn/webauthn to v0.12.3 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7422): fix(i18n): fix several usages of i18n + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7421): fix(migrations): transfer PR flow information + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7419): chore: add empty `action_variable` fixture + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7417): Update dependency go to v1.24.2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7416): chore(ui): remove fomantic's dimmer module + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7414): chore(ui): remove ineffective class small in inline code preview + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7408): chore: enable several no-jquery rules + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7407): Update vitest monorepo to v3.1.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7406): Update linters to v8.29.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7400): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7399): Update renovate to v39.222.1 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7397): [gitea] week 2025-13 cherry pick (gitea/main -> forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7396): chore: use dynamic id + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7394): use correct init instruction for sha256 + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7392): Lock file maintenance (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7391): Update github.com/google/pprof digest to a4b03ec (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7390): Accessibility: fix unreadable captcha with dark themes + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7384): Update linters (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7383): Update dependency yamllint to v1.37.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7382): Update vitest monorepo to v3.0.9 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7381): Update dependency @vitest/eslint-plugin to v1.1.38 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7379): prepend AppSubURL to visibility hint URLs + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7378): chore: improve repo migrate e2e test + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7376): chore(tests): fix testing failure caused by dep update + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7374): chore(tests): refactor migration form test + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7372): Update dependency eslint-plugin-unicorn to v58 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7371): chore: use correct import + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7367): Update module github.com/golangci/golangci-lint/cmd/golangci-lint to v2 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7366): Update https://data.forgejo.org/tj-actions/changed-files action to v46 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7362): Update module golang.org/x/net to v0.38.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7356): fix(ui): improve vertical alignment of icons with text in the overflow menu (#7314) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7355): 4108-empty-slice-encoded-to-null + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7350): refactor(cli): improve dump's temporary file handling + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7348): introduce gitNeeded bool in setup + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7344): fix(ui): Do not check for `vertical-align` + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7339): Update dependency mermaid to v11.6.0 (forgejo) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7337): chore: branding import path + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7314): fix(ui): improve vertical alignment of icons with text in the overflow menu + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7278): feat(build): lint-locale-usage should detect more Tr functions + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7271): feat(ui): improve button gap consistency, make it variable, larger on touchscreens + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7261): redirect to submodule instead of throwing 500 error when viewing submodule entry + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7203): add port and schema to federation host + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7092): feat(repo,locale): merge PR/issues cases for some repo/issue strings + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7035): enable HTTP signatures on all ActivityPub endpoints + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6977): feat!: Abusive content reporting + - [PR](https://codeberg.org/forgejo/forgejo/pulls/6154): Replace the 'relative-time' element scripting with custom, translatable rewrite +- Already announced in the release notes of an older stable release + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8234): collaborator can edit wiki with write access + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8189): do not ignore automerge while a PR is checking for conflicts + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8170): erroneous list continuation on Cmd+Enter (#8153) + - [PR](https://codeberg.org/forgejo/forgejo/pulls/8155): do not fail when release or wiki is set in `/repos/migrate` API + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7979): pull request cross references + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7976): ignore expired artifacts for quota calculation + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7883): quote reply in Chromium + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7775): make hash pattern more strict + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7755): fix(sec): add tests for OAuth2 signup + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7752): fix(sec): only degrade permission check for git push + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7650): display the list of tasks in the runner edit page + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7594): fix(i18n): prevent incorrect logging on strings missing in JSON locales + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7584): fix(ui/pr): use eye icon for reviews + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7581): fix(ui): use gap in switch items + - [PR](https://codeberg.org/forgejo/forgejo/pulls/7395): validate input for default_{merge,update}_style + diff --git a/renovate.json b/renovate.json index 7796490544..135df58c07 100644 --- a/renovate.json +++ b/renovate.json @@ -8,7 +8,8 @@ ], "baseBranches": [ "$default", - "/^v11\\.\\d+/forgejo$/" + "/^v11\\.\\d+/forgejo$/", + "/^v12\\.\\d+/forgejo$/" ], "postUpdateOptions": ["gomodTidy", "gomodUpdateImportPaths", "npmDedupe"], "prConcurrentLimit": 10, diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index c53edfbf96..721f96b768 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -117,7 +117,7 @@ func verifyAuth(r *web.Route, authMethods []auth.Method) { var err error ctx.Doer, err = authGroup.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session) if err != nil { - log.Error("Failed to verify user: %v", err) + log.Info("Failed to verify user: %v", err) ctx.Error(http.StatusUnauthorized, "authGroup.Verify") return } diff --git a/routers/api/packages/container/container.go b/routers/api/packages/container/container.go index 191a4aa455..117fc6ab88 100644 --- a/routers/api/packages/container/container.go +++ b/routers/api/packages/container/container.go @@ -437,11 +437,11 @@ func EndUploadBlob(ctx *context.Context) { return } + doClose = false if err := uploader.Close(); err != nil { apiError(ctx, http.StatusInternalServerError, err) return } - doClose = false if err := container_service.RemoveBlobUploadByID(ctx, uploader.ID); err != nil { apiError(ctx, http.StatusInternalServerError, err) diff --git a/routers/api/packages/helper/helper.go b/routers/api/packages/helper/helper.go index f9b91d9a09..47d1f18623 100644 --- a/routers/api/packages/helper/helper.go +++ b/routers/api/packages/helper/helper.go @@ -25,7 +25,8 @@ func LogAndProcessError(ctx *context.Context, status int, obj any, cb func(strin message = fmt.Sprintf("%s", obj) } if status == http.StatusInternalServerError { - log.ErrorWithSkip(1, message) + // LogAndProcessError is always wrapped in a `apiError` call, so we need to skip two frames + log.ErrorWithSkip(2, message) if setting.IsProd && (ctx.Doer == nil || !ctx.Doer.IsAdmin) { message = "" diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 549fe9fae0..6c1671d21c 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -241,7 +241,7 @@ func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEn return nil, nil, nil } - if entry.IsDir() || entry.IsSubModule() { + if entry.IsDir() || entry.IsSubmodule() { ctx.NotFound("getBlobForEntry", nil) return nil, nil, nil } diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 59538d8a0e..90ce2e0a71 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -920,25 +920,29 @@ func ExcerptBlob(ctx *context.Context) { ctx.Error(http.StatusInternalServerError, "getExcerptLines") return } - if idxRight > lastRight { + + // After the "up" or "down" expansion, check if there's any remaining content in the diff and add a line that will + // be rendered into a new expander at either the top, or bottom. + lineSection := &gitdiff.DiffLine{ + Type: gitdiff.DiffLineSection, + SectionInfo: &gitdiff.DiffLineSectionInfo{ + Path: filePath, + LastLeftIdx: lastLeft, + LastRightIdx: lastRight, + LeftIdx: idxLeft, + RightIdx: idxRight, + LeftHunkSize: leftHunkSize, + RightHunkSize: rightHunkSize, + }, + } + if lineSection.GetExpandDirection() != gitdiff.DiffLineExpandNone { lineText := " " if rightHunkSize > 0 || leftHunkSize > 0 { lineText = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize) } lineText = html.EscapeString(lineText) - lineSection := &gitdiff.DiffLine{ - Type: gitdiff.DiffLineSection, - Content: lineText, - SectionInfo: &gitdiff.DiffLineSectionInfo{ - Path: filePath, - LastLeftIdx: lastLeft, - LastRightIdx: lastRight, - LeftIdx: idxLeft, - RightIdx: idxRight, - LeftHunkSize: leftHunkSize, - RightHunkSize: rightHunkSize, - }, - } + lineSection.Content = lineText + switch direction { case "up": section.Lines = append([]*gitdiff.DiffLine{lineSection}, section.Lines...) diff --git a/routers/web/repo/download.go b/routers/web/repo/download.go index fc82ece4cb..9fb4d78fe3 100644 --- a/routers/web/repo/download.go +++ b/routers/web/repo/download.go @@ -92,7 +92,7 @@ func getBlobForEntry(ctx *context.Context) (*git.Blob, *time.Time) { return nil, nil } - if entry.IsDir() || entry.IsSubModule() { + if entry.IsDir() || entry.IsSubmodule() { ctx.NotFound("getBlobForEntry", nil) return nil, nil } diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index a4f6f97a05..7ab9d62b69 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -2401,10 +2401,6 @@ func UpdateIssueMilestone(ctx *context.Context) { } if ctx.FormBool("htmx") { - renderMilestones(ctx) - if ctx.Written() { - return - } prepareHiddenCommentType(ctx) if ctx.Written() { return diff --git a/routers/web/repo/treelist.go b/routers/web/repo/treelist.go index 5c37f2ebca..20ea9babbe 100644 --- a/routers/web/repo/treelist.go +++ b/routers/web/repo/treelist.go @@ -42,7 +42,7 @@ func isExcludedEntry(entry *git.TreeEntry) bool { return true } - if entry.IsSubModule() { + if entry.IsSubmodule() { return true } diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index d00f85a134..e61059da64 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -1057,14 +1057,13 @@ func renderHomeCode(ctx *context.Context) { return } - if entry.IsSubModule() { - subModuleURL, err := ctx.Repo.Commit.GetSubModule(entry.Name()) + if entry.IsSubmodule() { + submodule, err := ctx.Repo.Commit.GetSubmodule(ctx.Repo.TreePath, entry) if err != nil { - HandleGitError(ctx, "Repo.Commit.GetSubModule", err) + HandleGitError(ctx, "Repo.Commit.GetSubmodule", err) return } - subModuleFile := git.NewSubModuleFile(ctx.Repo.Commit, subModuleURL, entry.ID.String()) - ctx.Redirect(subModuleFile.RefURL(setting.AppURL, ctx.Repo.Repository.FullName(), setting.SSH.Domain)) + ctx.Redirect(submodule.ResolveUpstreamURL(ctx.Repo.Repository.HTMLURL())) } else if entry.IsDir() { renderDirectory(ctx) } else { diff --git a/routers/web/web.go b/routers/web/web.go index 534c37e918..01a6ea0083 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -118,7 +118,7 @@ func webAuth(authMethod auth_service.Method) func(*context.Context) { return func(ctx *context.Context) { ar, err := common.AuthShared(ctx.Base, ctx.Session, authMethod) if err != nil { - log.Error("Failed to verify user: %v", err) + log.Info("Failed to verify user: %v", err) ctx.Error(http.StatusUnauthorized, ctx.Locale.TrString("auth.unauthorized_credentials", "https://codeberg.org/forgejo/forgejo/issues/2809")) return } diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 7033264f18..1f2a7f232f 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -85,11 +85,20 @@ type DiffLine struct { // DiffLineSectionInfo represents diff line section meta data type DiffLineSectionInfo struct { - Path string - LastLeftIdx int - LastRightIdx int - LeftIdx int - RightIdx int + Path string + + // Last(Left/Right)Idx do not directly relate to this diff section, but indicate the last line number in the + // previous diff section. Set to 0 for the first diff section of a file, and 1 for the first line of code in the + // file. + LastLeftIdx int + LastRightIdx int + + // (Left/Right)Idx are the first line number in this diff section + LeftIdx int + RightIdx int + + // Number of lines contained within each diff section. In the UI, these fields are set to 0 in cases where a + // section is being used as a placeholder at the end of a diff to allow expansion into the remainder of the file. LeftHunkSize int RightHunkSize int } @@ -157,7 +166,7 @@ func (d *DiffLine) GetExpandDirection() DiffLineExpandDirection { } if d.SectionInfo.LastLeftIdx <= 0 && d.SectionInfo.LastRightIdx <= 0 { return DiffLineExpandUp - } else if d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx > BlobExcerptChunkSize && d.SectionInfo.RightHunkSize > 0 { + } else if d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx-1 > BlobExcerptChunkSize && d.SectionInfo.RightHunkSize > 0 { return DiffLineExpandUpDown } else if d.SectionInfo.LeftHunkSize <= 0 && d.SectionInfo.RightHunkSize <= 0 { return DiffLineExpandDown diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index 695b177b8b..d4d1cd4460 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -717,6 +717,163 @@ func TestGetDiffFull(t *testing.T) { }) } +func TestDiffLine_GetExpandDirection(t *testing.T) { + tests := []struct { + name string + diffLine *DiffLine + expectedResult DiffLineExpandDirection + }{ + { + name: "non-section line - no expansion", + diffLine: &DiffLine{ + Type: DiffLineAdd, + SectionInfo: &DiffLineSectionInfo{}, + }, + expectedResult: DiffLineExpandNone, + }, + { + name: "nil section info - no expansion", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: nil, + }, + expectedResult: DiffLineExpandNone, + }, + { + name: "no lines between", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: &DiffLineSectionInfo{ + // Previous section of the diff displayed up to line 530... + LastRightIdx: 530, + LastLeftIdx: 530, + // This section of the diff starts at line 531... + RightIdx: 531, + LeftIdx: 531, + }, + }, + // There are zero lines between 530 and 531, so we should have nothing to expand. + expectedResult: DiffLineExpandNone, + }, + { + name: "first diff section is the start of the file", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: &DiffLineSectionInfo{ + // Last[...]Idx is set to zero when it's the first section in the file (and not 1, which would be + // the first section -is- the first line of the file). + LastRightIdx: 0, + LastLeftIdx: 0, + // The diff section is showing line 1, the top of th efile. + RightIdx: 1, + LeftIdx: 1, + }, + }, + // We're at the top of the file; no expansion. + expectedResult: DiffLineExpandNone, + }, + { + name: "first diff section doesn't start at the top of the file", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: &DiffLineSectionInfo{ + // Last[...]Idx is set to zero when it's the first section in the file (and not 1, which would be + // the first section -is- the first line of the file). + LastRightIdx: 0, + LastLeftIdx: 0, + RightIdx: 531, + LeftIdx: 531, + }, + }, + // We're at the top of the diff but there's content above, so can only expand up. + expectedResult: DiffLineExpandUp, + }, + { + name: "middle of the file with single expansion", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: &DiffLineSectionInfo{ + // Previous section ended at ~500... + LastRightIdx: 500, + LastLeftIdx: 500, + // Next section starts one line away... + RightIdx: 502, + LeftIdx: 502, + // The next block has content (> 0) + RightHunkSize: 50, + LeftHunkSize: 50, + }, + }, + // Can be expanded in a single direction, displaying the missing line (501). + expectedResult: DiffLineExpandSingle, + }, + { + name: "middle of the file with multi line expansion", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: &DiffLineSectionInfo{ + // Previous section ended at ~500... + LastRightIdx: 500, + LastLeftIdx: 500, + // Lines 501-520 are hidden, exactly 20 lines, matching BlobExcerptChunkSize (20)... + RightIdx: 521, + LeftIdx: 521, + // The next block has content (> 0) + RightHunkSize: 50, + LeftHunkSize: 50, + }, + }, + // Can be expanded in a single direction, displaying all the hidden 20 lines. + expectedResult: DiffLineExpandSingle, + }, + { + name: "middle of the file with multi direction expansion", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: &DiffLineSectionInfo{ + // Previous section ended at ~500... + LastRightIdx: 500, + LastLeftIdx: 500, + // Lines 501-521 are hidden, exactly 21 lines, exceeding BlobExcerptChunkSize (20)... + RightIdx: 522, + LeftIdx: 522, + // The next block has content (> 0) + RightHunkSize: 50, + LeftHunkSize: 50, + }, + }, + // Now can be expanded down to display from 501-520 (521 remains hidden), or up to display 502-521 (501 + // remains hidden). + expectedResult: DiffLineExpandUpDown, + }, + { + name: "end of the diff but still file content to display", + diffLine: &DiffLine{ + Type: DiffLineSection, + SectionInfo: &DiffLineSectionInfo{ + // We had a previous diff section, of any size/location... + LastRightIdx: 200, + LastLeftIdx: 200, + RightIdx: 531, + LeftIdx: 531, + // Hunk size size 0 is a placeholder value for the end or beginning of a file... + RightHunkSize: 0, + LeftHunkSize: 0, + }, + }, + // Combination of conditions says we're at the end of the last diff section, can only expand down. + expectedResult: DiffLineExpandDown, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.diffLine.GetExpandDirection() + assert.Equal(t, tt.expectedResult, result) + }) + } +} + func TestNoCrashes(t *testing.T) { type testcase struct { gitdiff string diff --git a/services/pull/check.go b/services/pull/check.go index 6002e2ae26..c31d107605 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -404,6 +404,10 @@ func CheckPRsForBaseBranch(ctx context.Context, baseRepo *repo_model.Repository, // Init runs the task queue to test all the checking status pull requests func Init() error { + if err := LoadMergeMessageTemplates(); err != nil { + return err + } + prPatchCheckerQueue = queue.CreateUniqueQueue(graceful.GetManager().ShutdownContext(), "pr_patch_checker", handler) if prPatchCheckerQueue == nil { diff --git a/services/pull/merge.go b/services/pull/merge.go index f69f8a87b4..55ce869497 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -35,6 +35,30 @@ import ( notify_service "forgejo.org/services/notify" ) +var mergeMessageTemplates = make(map[repo_model.MergeStyle]string, len(repo_model.MergeStyles)) + +func LoadMergeMessageTemplates() error { + // Load templates for all known merge styles + for _, mergeStyle := range repo_model.MergeStyles { + templateFilename := filepath.Join( + setting.CustomPath, + "default_merge_message", + fmt.Sprintf("%s_TEMPLATE.md", strings.ToUpper(string(mergeStyle))), + ) + + content, err := os.ReadFile(templateFilename) + if err == nil { + mergeMessageTemplates[mergeStyle] = string(content) + } else if os.IsNotExist(err) { + // The file no longer exists, so delete any previous content + delete(mergeMessageTemplates, mergeStyle) + } else { + return err + } + } + return nil +} + // getMergeMessage composes the message used when merging a pull request. func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issues_model.PullRequest, mergeStyle repo_model.MergeStyle, extraVars map[string]string) (message, body string, err error) { if err := pr.LoadBaseRepo(ctx); err != nil { @@ -79,6 +103,13 @@ func getMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr *issue if _, ok := err.(git.ErrNotExist); ok { templateContent, err = commit.GetFileContent(templateFilepathGitea, setting.Repository.PullRequest.DefaultMergeMessageSize) } + + if _, ok := err.(git.ErrNotExist); ok { + if preloadedContent, ok := mergeMessageTemplates[mergeStyle]; ok { + templateContent, err = preloadedContent, nil + } + } + if err != nil { if !git.IsErrNotExist(err) { return "", "", err diff --git a/services/pull/merge_test.go b/services/pull/merge_test.go index 2a26759956..3684c2120a 100644 --- a/services/pull/merge_test.go +++ b/services/pull/merge_test.go @@ -4,9 +4,17 @@ package pull import ( + "os" + "path" + "strings" "testing" + repo_model "forgejo.org/models/repo" + "forgejo.org/modules/setting" + "forgejo.org/modules/test" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_expandDefaultMergeMessage(t *testing.T) { @@ -90,3 +98,51 @@ func TestAddCommitMessageTailer(t *testing.T) { assert.Equal(t, "title\n\nTest-tailer: v1\nTest-tailer: v2", AddCommitMessageTrailer("title\n\nTest-tailer: v1", "Test-tailer", "v2")) assert.Equal(t, "title\n\nTest-tailer: v1\nTest-tailer: v2", AddCommitMessageTrailer("title\n\nTest-tailer: v1\n", "Test-tailer", "v2")) } + +func prepareLoadMergeMessageTemplates(targetDir string) error { + for _, template := range []string{"MERGE", "REBASE", "REBASE-MERGE", "SQUASH", "MANUALLY-MERGED", "REBASE-UPDATE-ONLY"} { + file, err := os.Create(path.Join(targetDir, template+"_TEMPLATE.md")) + defer file.Close() + + if err == nil { + _, err = file.WriteString("Contents for " + template) + } + + if err != nil { + return err + } + } + + return nil +} + +func TestLoadMergeMessageTemplates(t *testing.T) { + defer test.MockVariableValue(&setting.CustomPath, t.TempDir())() + templateTemp := path.Join(setting.CustomPath, "default_merge_message") + + require.NoError(t, os.MkdirAll(templateTemp, 0o755)) + require.NoError(t, prepareLoadMergeMessageTemplates(templateTemp)) + + testStyles := []repo_model.MergeStyle{ + repo_model.MergeStyleMerge, + repo_model.MergeStyleRebase, + repo_model.MergeStyleRebaseMerge, + repo_model.MergeStyleSquash, + repo_model.MergeStyleManuallyMerged, + repo_model.MergeStyleRebaseUpdate, + } + + // Load all templates + require.NoError(t, LoadMergeMessageTemplates()) + + // Check their correctness + assert.Len(t, mergeMessageTemplates, len(testStyles)) + for _, mergeStyle := range testStyles { + assert.Equal(t, "Contents for "+strings.ToUpper(string(mergeStyle)), mergeMessageTemplates[mergeStyle]) + } + + // Unload all templates + require.NoError(t, os.RemoveAll(templateTemp)) + require.NoError(t, LoadMergeMessageTemplates()) + assert.Empty(t, mergeMessageTemplates) +} diff --git a/services/pull/patch.go b/services/pull/patch.go index 37a0f818e9..89581c916b 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -106,12 +106,15 @@ func (t *testPatchContext) LoadHeadRevision(ctx context.Context, pr *issues_mode } // getTestPatchCtx constructs a new testpatch context for the given pull request. -func getTestPatchCtx(ctx context.Context, pr *issues_model.PullRequest) (*testPatchContext, error) { +// If `onBare` is true, then the context will use the base repository that does +// not contain a working tree. Otherwise a temprorary repository is created that +// contains a working tree. +func getTestPatchCtx(ctx context.Context, pr *issues_model.PullRequest, onBare bool) (*testPatchContext, error) { testPatchCtx := &testPatchContext{ close: func() {}, } - if git.SupportGitMergeTree { + if onBare { if err := pr.LoadBaseRepo(ctx); err != nil { return testPatchCtx, fmt.Errorf("LoadBaseRepo: %w", err) } @@ -157,7 +160,7 @@ func getTestPatchCtx(ctx context.Context, pr *issues_model.PullRequest) (*testPa } func testPatch(ctx context.Context, pr *issues_model.PullRequest) (*testPatchContext, error) { - testPatchCtx, err := getTestPatchCtx(ctx, pr) + testPatchCtx, err := getTestPatchCtx(ctx, pr, git.SupportGitMergeTree) if err != nil { return testPatchCtx, fmt.Errorf("getTestPatchCtx: %w", err) } diff --git a/services/pull/pull.go b/services/pull/pull.go index 26210f7156..c1fe6c6b55 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -4,11 +4,9 @@ package pull import ( - "bytes" "context" "fmt" "io" - "os" "regexp" "strings" "time" @@ -30,7 +28,6 @@ import ( repo_module "forgejo.org/modules/repository" "forgejo.org/modules/setting" "forgejo.org/modules/sync" - "forgejo.org/modules/util" gitea_context "forgejo.org/services/context" issue_service "forgejo.org/services/issue" notify_service "forgejo.org/services/notify" @@ -384,98 +381,51 @@ func TestPullRequest(ctx context.Context, doer *user_model.User, repoID, olderTh // Update commit divergence. func ValidatePullRequest(ctx context.Context, pr *issues_model.PullRequest, newCommitID, oldCommitID string, doer *user_model.User) { objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName) - if newCommitID != "" && newCommitID != objectFormat.EmptyObjectID().String() { - changed, err := checkIfPRContentChanged(ctx, pr, oldCommitID, newCommitID) + if newCommitID == "" || newCommitID == objectFormat.EmptyObjectID().String() { + return + } + + testPatchCtx, err := getTestPatchCtx(ctx, pr, true) + defer testPatchCtx.close() + if err != nil { + log.Error("testPatchCtx: %v", err) + return + } + + changed, err := testPatchCtx.gitRepo.CheckIfDiffDiffers(testPatchCtx.baseRev, oldCommitID, newCommitID, testPatchCtx.env) + if err != nil { + log.Error("CheckIfDiffDiffers: %v", err) + } + if changed { + if err := issues_model.MarkReviewsAsStale(ctx, pr.IssueID); err != nil { + log.Error("MarkReviewsAsStale: %v", err) + } + + pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch) if err != nil { - log.Error("checkIfPRContentChanged: %v", err) + log.Error("GetFirstMatchProtectedBranchRule: %v", err) } - if changed { - if err := issues_model.MarkReviewsAsStale(ctx, pr.IssueID); err != nil { - log.Error("MarkReviewsAsStale: %v", err) + if pb != nil && pb.DismissStaleApprovals { + if err := DismissApprovalReviews(ctx, doer, pr); err != nil { + log.Error("DismissApprovalReviews: %v", err) } + } + } + if err := issues_model.MarkReviewsAsNotStale(ctx, pr.IssueID, newCommitID); err != nil { + log.Error("MarkReviewsAsNotStale: %v", err) + } - pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch) - if err != nil { - log.Error("GetFirstMatchProtectedBranchRule: %v", err) - } - if pb != nil && pb.DismissStaleApprovals { - if err := DismissApprovalReviews(ctx, doer, pr); err != nil { - log.Error("DismissApprovalReviews: %v", err) - } - } - } - if err := issues_model.MarkReviewsAsNotStale(ctx, pr.IssueID, newCommitID); err != nil { - log.Error("MarkReviewsAsNotStale: %v", err) - } - divergence, err := GetDiverging(ctx, pr) + divergence, err := git.GetDivergingCommits(ctx, testPatchCtx.gitRepo.Path, testPatchCtx.baseRev, testPatchCtx.headRev, testPatchCtx.env) + if err != nil { + log.Error("GetDivergingCommits: %v", err) + } else { + err = pr.UpdateCommitDivergence(ctx, divergence.Ahead, divergence.Behind) if err != nil { - log.Error("GetDiverging: %v", err) - } else { - err = pr.UpdateCommitDivergence(ctx, divergence.Ahead, divergence.Behind) - if err != nil { - log.Error("UpdateCommitDivergence: %v", err) - } + log.Error("UpdateCommitDivergence: %v", err) } } } -// checkIfPRContentChanged checks if diff to target branch has changed by push -// A commit can be considered to leave the PR untouched if the patch/diff with its merge base is unchanged -func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) { - prCtx, cancel, err := createTemporaryRepoForPR(ctx, pr) - if err != nil { - log.Error("CreateTemporaryRepoForPR %-v: %v", pr, err) - return false, err - } - defer cancel() - - tmpRepo, err := git.OpenRepository(ctx, prCtx.tmpBasePath) - if err != nil { - return false, fmt.Errorf("OpenRepository: %w", err) - } - defer tmpRepo.Close() - - // Find the merge-base - _, base, err := tmpRepo.GetMergeBase("", "base", "tracking") - if err != nil { - return false, fmt.Errorf("GetMergeBase: %w", err) - } - - cmd := git.NewCommand(ctx, "diff", "--name-only", "-z").AddDynamicArguments(newCommitID, oldCommitID, base) - stdoutReader, stdoutWriter, err := os.Pipe() - if err != nil { - return false, fmt.Errorf("unable to open pipe for to run diff: %w", err) - } - - stderr := new(bytes.Buffer) - if err := cmd.Run(&git.RunOpts{ - Dir: prCtx.tmpBasePath, - Stdout: stdoutWriter, - Stderr: stderr, - PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { - _ = stdoutWriter.Close() - defer func() { - _ = stdoutReader.Close() - }() - return util.IsEmptyReader(stdoutReader) - }, - }); err != nil { - if err == util.ErrNotEmpty { - return true, nil - } - err = git.ConcatenateError(err, stderr.String()) - - log.Error("Unable to run diff on %s %s %s in tempRepo for PR[%d]%s/%s...%s/%s: Error: %v", - newCommitID, oldCommitID, base, - pr.ID, pr.BaseRepo.FullName(), pr.BaseBranch, pr.HeadRepo.FullName(), pr.HeadBranch, - err) - - return false, fmt.Errorf("Unable to run git diff --name-only -z %s %s %s: %w", newCommitID, oldCommitID, base, err) - } - - return false, nil -} - // PushToBaseRepo pushes commits from branches of head repository to // corresponding branches of base repository. // FIXME: Only push branches that are actually updates? diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go index 010b7a6404..99607c5b35 100644 --- a/services/pull/pull_test.go +++ b/services/pull/pull_test.go @@ -92,3 +92,39 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { assert.Equal(t, "Merge pull request 'issue3' (#3) from user2/repo2:branch2 into master", mergeMessage) } + +func TestPullRequest_GetDefaultMergeMessage_GlobalTemplate(t *testing.T) { + require.NoError(t, unittest.PrepareTestDatabase()) + pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) + + require.NoError(t, pr.LoadBaseRepo(t.Context())) + gitRepo, err := gitrepo.OpenRepository(t.Context(), pr.BaseRepo) + require.NoError(t, err) + defer gitRepo.Close() + + templateRepo, err := git.OpenRepository(t.Context(), "./../../modules/git/tests/repos/templates_repo") + require.NoError(t, err) + defer templateRepo.Close() + + mergeMessageTemplates[repo_model.MergeStyleMerge] = "${PullRequestTitle} (${PullRequestReference})\n${PullRequestDescription}" + + // Check template is used for Merge... + mergeMessage, body, err := GetDefaultMergeMessage(t.Context(), gitRepo, pr, repo_model.MergeStyleMerge) + require.NoError(t, err) + + assert.Equal(t, "issue3 (#3)", mergeMessage) + assert.Equal(t, "content for the third issue", body) + + // ...but not for RebaseMerge + mergeMessage, _, err = GetDefaultMergeMessage(t.Context(), gitRepo, pr, repo_model.MergeStyleRebaseMerge) + require.NoError(t, err) + + assert.Equal(t, "Merge pull request 'issue3' (#3) from branch2 into master", mergeMessage) + + // ...and that custom Merge template takes priority + mergeMessage, body, err = GetDefaultMergeMessage(t.Context(), templateRepo, pr, repo_model.MergeStyleMerge) + require.NoError(t, err) + + assert.Equal(t, "Default merge message template", mergeMessage) + assert.Equal(t, "This line was read from .forgejo/default_merge_message/MERGE_TEMPLATE.md", body) +} diff --git a/services/pull/review.go b/services/pull/review.go index 7d232d6d79..b0ab700fa6 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -298,10 +298,16 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos if headCommitID == commitID { stale = false } else { - stale, err = checkIfPRContentChanged(ctx, pr, commitID, headCommitID) + testPatchCtx, err := getTestPatchCtx(ctx, pr, true) + defer testPatchCtx.close() if err != nil { return nil, nil, err } + + stale, err = testPatchCtx.gitRepo.CheckIfDiffDiffers(testPatchCtx.baseRev, commitID, headCommitID, testPatchCtx.env) + if err != nil { + return nil, nil, fmt.Errorf("CheckIfDiffDiffers: %w", err) + } } } diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 5a6006e9f2..d701508ff0 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -108,7 +108,7 @@ func GetObjectTypeFromTreeEntry(entry *git.TreeEntry) ContentType { switch { case entry.IsDir(): return ContentTypeDir - case entry.IsSubModule(): + case entry.IsSubmodule(): return ContentTypeSubmodule case entry.IsExecutable(), entry.IsRegular(): return ContentTypeRegular @@ -211,14 +211,14 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref return nil, err } contentsResponse.Target = &targetFromContent - } else if entry.IsSubModule() { + } else if entry.IsSubmodule() { contentsResponse.Type = string(ContentTypeSubmodule) - submoduleURL, err := commit.GetSubModule(treePath) + submodule, err := commit.GetSubmodule(treePath, entry) if err != nil { return nil, err } - if submoduleURL != "" { - contentsResponse.SubmoduleGitURL = &submoduleURL + if submodule.URL != "" { + contentsResponse.SubmoduleGitURL = &submodule.URL } } // Handle links @@ -230,7 +230,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref downloadURLString := downloadURL.String() contentsResponse.DownloadURL = &downloadURLString } - if !entry.IsSubModule() { + if !entry.IsSubmodule() { htmlURL, err := url.Parse(repo.HTMLURL() + "/src/" + url.PathEscape(string(refType)) + "/" + util.PathEscapeSegments(ref) + "/" + util.PathEscapeSegments(treePath)) if err != nil { return nil, err diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go index 1e575f95e8..5a369b27a5 100644 --- a/services/repository/files/tree.go +++ b/services/repository/files/tree.go @@ -87,7 +87,7 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git if entries[e].IsDir() { copy(treeURL[copyPos:], entries[e].ID.String()) tree.Entries[i].URL = string(treeURL) - } else if entries[e].IsSubModule() { + } else if entries[e].IsSubmodule() { // In Github Rest API Version=2022-11-28, if a tree entry is a submodule, // its url will be returned as an empty string. // So the URL will be set to "" here. diff --git a/templates/htmx/milestone_sidebar.tmpl b/templates/htmx/milestone_sidebar.tmpl index 05bbd802cc..87eb5a7f42 100644 --- a/templates/htmx/milestone_sidebar.tmpl +++ b/templates/htmx/milestone_sidebar.tmpl @@ -1,4 +1,4 @@
{{template "repo/issue/view_content/comments" .}}
-{{template "repo/issue/view_content/sidebar/milestones" .}} +{{template "repo/issue/milestone/selected" .}} diff --git a/templates/repo/issue/milestone/selected.tmpl b/templates/repo/issue/milestone/selected.tmpl new file mode 100644 index 0000000000..c5ed4c81af --- /dev/null +++ b/templates/repo/issue/milestone/selected.tmpl @@ -0,0 +1,11 @@ +
+ {{ctx.Locale.Tr "repo.issues.new.no_milestone"}} + +
diff --git a/templates/repo/issue/view_content/sidebar/milestones.tmpl b/templates/repo/issue/view_content/sidebar/milestones.tmpl index 44d9419f9b..ffcd87e8fd 100644 --- a/templates/repo/issue/view_content/sidebar/milestones.tmpl +++ b/templates/repo/issue/view_content/sidebar/milestones.tmpl @@ -1,4 +1,4 @@ - diff --git a/templates/repo/issue/view_content/sidebar/reference.tmpl b/templates/repo/issue/view_content/sidebar/reference.tmpl index bbbc099558..1b24531b7b 100644 --- a/templates/repo/issue/view_content/sidebar/reference.tmpl +++ b/templates/repo/issue/view_content/sidebar/reference.tmpl @@ -1,7 +1,14 @@ -
+
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}} -
- {{ctx.Locale.Tr "repo.issues.reference_link" $issueReferenceLink}} - + + + {{ctx.Locale.Tr "discussion.sidebar.reference"}} + + +
+
+ {{$issueReferenceLink}} + +
diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index c8061a75b0..0fd00ebff1 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -292,7 +292,7 @@
-

{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "forgejo"}}

+

{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "Forgejo"}}

diff --git a/templates/repo/settings/push_mirror_sync_modal.tmpl b/templates/repo/settings/push_mirror_sync_modal.tmpl index 32f0994f03..00b1b9dcd5 100644 --- a/templates/repo/settings/push_mirror_sync_modal.tmpl +++ b/templates/repo/settings/push_mirror_sync_modal.tmpl @@ -24,7 +24,7 @@
-

{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "forgejo"}}

+

{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "Forgejo"}}