mirror of
https://codeberg.org/davrot/forgejo.git
synced 2025-07-22 16:00:03 +02:00
Compare commits
27 commits
aaa1f333bf
...
d0e4cdc193
Author | SHA1 | Date | |
---|---|---|---|
d0e4cdc193 | |||
95c10cb239 | |||
![]() |
c66062eaef | ||
![]() |
5645456cac | ||
![]() |
dd3f24deef | ||
![]() |
501cc5c7c5 | ||
![]() |
8efb6c09db | ||
![]() |
0e1bafdff3 | ||
![]() |
772bb20875 | ||
![]() |
09c9108a35 | ||
![]() |
ec8c0a50c2 | ||
![]() |
d61bd928a4 | ||
![]() |
93f029cb75 | ||
![]() |
1695ff8125 | ||
![]() |
7f6b9a8867 | ||
![]() |
ac43750ada | ||
![]() |
e47fa23729 | ||
![]() |
e186b5c039 | ||
![]() |
5158493ba6 | ||
![]() |
48cc6e684a | ||
![]() |
f1fc008d02 | ||
![]() |
1937fcf476 | ||
![]() |
81e59014da | ||
![]() |
e4bf651aa7 | ||
![]() |
d07821d275 | ||
![]() |
9f5e1157f0 | ||
![]() |
f666b882a8 |
97 changed files with 3044 additions and 979 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
2
Makefile
2
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: ...
|
||||
|
|
8
go.mod
8
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
|
||||
|
|
12
go.sum
12
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=
|
||||
|
|
16
models/fixtures/TestAddTeamReviewRequest/issue.yml
Normal file
16
models/fixtures/TestAddTeamReviewRequest/issue.yml
Normal file
|
@ -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
|
|
@ -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
|
12
models/fixtures/TestAddTeamReviewRequest/pull_request.yml
Normal file
12
models/fixtures/TestAddTeamReviewRequest/pull_request.yml
Normal file
|
@ -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
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ const (
|
|||
MergeStyleRebaseUpdate MergeStyle = "rebase-update-only"
|
||||
)
|
||||
|
||||
var MergeStyles = []MergeStyle{MergeStyleMerge, MergeStyleRebase, MergeStyleRebaseMerge, MergeStyleSquash, MergeStyleFastForwardOnly, MergeStyleManuallyMerged, MergeStyleRebaseUpdate}
|
||||
|
||||
type UpdateStyle string
|
||||
|
||||
const (
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
56
modules/git/diff_compare.go
Normal file
56
modules/git/diff_compare.go
Normal file
|
@ -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
|
||||
}
|
421
modules/git/diff_compare_test.go
Normal file
421
modules/git/diff_compare_test.go
Normal file
|
@ -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)
|
||||
})
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
1
modules/git/tests/repos/templates_repo/COMMIT_EDITMSG
Normal file
1
modules/git/tests/repos/templates_repo/COMMIT_EDITMSG
Normal file
|
@ -0,0 +1 @@
|
|||
Initial
|
1
modules/git/tests/repos/templates_repo/HEAD
Normal file
1
modules/git/tests/repos/templates_repo/HEAD
Normal file
|
@ -0,0 +1 @@
|
|||
ref: refs/heads/master
|
5
modules/git/tests/repos/templates_repo/config
Normal file
5
modules/git/tests/repos/templates_repo/config
Normal file
|
@ -0,0 +1,5 @@
|
|||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = true
|
||||
logallrefupdates = true
|
1
modules/git/tests/repos/templates_repo/description
Normal file
1
modules/git/tests/repos/templates_repo/description
Normal file
|
@ -0,0 +1 @@
|
|||
Unnamed repository; edit this file 'description' to name the repository.
|
BIN
modules/git/tests/repos/templates_repo/index
Normal file
BIN
modules/git/tests/repos/templates_repo/index
Normal file
Binary file not shown.
6
modules/git/tests/repos/templates_repo/info/exclude
Normal file
6
modules/git/tests/repos/templates_repo/info/exclude
Normal file
|
@ -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]
|
||||
# *~
|
1
modules/git/tests/repos/templates_repo/info/refs
Normal file
1
modules/git/tests/repos/templates_repo/info/refs
Normal file
|
@ -0,0 +1 @@
|
|||
45697427ce0595075c5c8efa42567f050208510d refs/heads/master
|
BIN
modules/git/tests/repos/templates_repo/objects/info/commit-graph
Normal file
BIN
modules/git/tests/repos/templates_repo/objects/info/commit-graph
Normal file
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
P pack-abb44544ae19d590e95822e963f78d069d27ba9e.pack
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
2
modules/git/tests/repos/templates_repo/packed-refs
Normal file
2
modules/git/tests/repos/templates_repo/packed-refs
Normal file
|
@ -0,0 +1,2 @@
|
|||
# pack-refs with: peeled fully-peeled sorted
|
||||
45697427ce0595075c5c8efa42567f050208510d refs/heads/master
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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] == "<span" || token[0:6] == "</span")) {
|
||||
count++
|
||||
|
@ -132,15 +135,15 @@ func HighlightSearchResultCode(filename string, lineNums []int, highlightRanges
|
|||
continue
|
||||
}
|
||||
|
||||
switch count {
|
||||
case end:
|
||||
switch {
|
||||
case count >= 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])
|
||||
}
|
||||
|
|
122
modules/indexer/code/search_test.go
Normal file
122
modules/indexer/code/search_test.go
Normal file
|
@ -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 <span class=\"search-highlight\">this</span> 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 <span class=\"search-highlight\">this</span> only",
|
||||
"Mark <span class=\"search-highlight\">this</span> 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 👉 <span class=\"search-highlight\">this</span> 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 <span class=\"search-highlight\">this 😊</span> 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 👉 <span class=\"search-highlight\">this 😊</span> 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{
|
||||
"<span class=\"kd\">func</span> <span class=\"nf\">main</span><span class=\"p\">(</span><span class=\"p\">)</span> <span class=\"p\">{</span>",
|
||||
"\t<span class=\"nx\">fmt</span><span class=\"p\">.</span><span class=\"nf\">Println</span><span class=\"p\">(</span><span class=\"s\">"<span class=\"search-highlight\">mark this</span>"</span><span class=\"p\">)</span>",
|
||||
"<span class=\"p\">}</span>",
|
||||
},
|
||||
},
|
||||
{
|
||||
Title: "Golang Unicode",
|
||||
File: "test.go",
|
||||
Range: [][3]int{{1, 14, 28}},
|
||||
Code: "func main() {\n\tfmt.Println(\"mark this 😊\")\n}",
|
||||
Result: []template.HTML{
|
||||
"<span class=\"kd\">func</span> <span class=\"nf\">main</span><span class=\"p\">(</span><span class=\"p\">)</span> <span class=\"p\">{</span>",
|
||||
"\t<span class=\"nx\">fmt</span><span class=\"p\">.</span><span class=\"nf\">Println</span><span class=\"p\">(</span><span class=\"s\">"<span class=\"search-highlight\">mark this 😊</span>"</span><span class=\"p\">)</span>",
|
||||
"<span class=\"p\">}</span>",
|
||||
},
|
||||
},
|
||||
}
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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 = الصفحة التي تحاول الوصول لها إما <strong>لا توجد</strong> أو <strong>أنت لست مأذون لك</strong> بعرضها.
|
||||
error404 = الصفحة التي تحاول الوصول لها إما <strong>غير موجودو</strong> أو <strong>أنك غير مصرح لك</strong> بعرضها.
|
||||
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" <email@example.com>.
|
||||
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 = <b>@%[1]s</b> علّم هذا الطلب للسحب كجاهز للمراجعة.
|
||||
issue_assigned.pull = @%[1]s عيّنك إلى طلب سحب %[2]s في مستودع %[3]s.
|
||||
issue.action.review_dismissed = <b>@%[1]s</b> أستبعد آخر مراجعة من %[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 = نشاطك مرئي لك ولسُعاة المثيل فقط. <a href="%s">تعديل الإعدادات</a>.
|
||||
followers_one = %d متابِع
|
||||
following.title.one = متابعة
|
||||
followers.title.few = متابعين
|
||||
following_one = %d يُتابع
|
||||
following.title.few = متابعة
|
||||
public_activity.visibility_hint.self_public = نشاطك مرئي للجميع، باستثناء التفاعلات في المساحات الخاصة. <a href="%s">اضبط الإعدادات</a>.
|
||||
public_activity.visibility_hint.admin_public = هذا النشاط مرئي للجميع، ولكن بصفتك مسؤولاً يمكنك أيضًا رؤية التفاعلات في المساحات الخاصة.
|
||||
public_activity.visibility_hint.self_private_profile = نشاطك مرئي لك ولسُعاة المثيل فقط لأن ملفك الشخصي خاص. <a href="%s">تعديل الإعدادات</a>.
|
||||
|
||||
[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، لديك عنوان بريد إلكتروني غير مؤكَّد (<b>%s</b>). إن لم تستلم رسالة تأكيد أو تريد إرسال واحدة جديدة، فنرجو الضغط على الزر الذي بالأسفل.
|
||||
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 = تم إرسال بريد تأكيد جديد إلى <b>%s</b>. يرجى التأكد من صندوق بريدك في خلال %s حتى تكتمل عملية التسجيل. إذا كان عنوان البريد خاطئ، يمكنك تسجيل الدخول وطلب بريد تأكيد جديد يُرسل إلى عنوان آخر.
|
||||
scratch_code = رمز الخدش
|
||||
invalid_code_forgot_password = رمز تأكيدك غير صحيح أو انتهى اضغط <a href="%s">هنا</a> للإعادة.
|
||||
invalid_code_forgot_password = رمز تأكيدك غير صحيح أو انتهت صلاحيته. اضغط <a href="%s">هنا</a> للإعادة.
|
||||
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 = تم إرسال بريد تأكيد جديد إلى <b>%s</b>. يرجى التأكد من صندوق بريدك في خلال %s حتى تكتمل عملية استعادة الحساب.
|
||||
|
@ -1513,6 +1560,13 @@ openid_register_desc = مسار الـOpenID المختار مجهول. اربط
|
|||
remember_me = تذكر هذا الجهاز
|
||||
remember_me.compromised = رمز الاحتفاظ بتسجيل الدخول لم يعد صالحا، مما قد يعني اختراق الحساب. نرجو مراجعة حسابك لرؤية أي نشاط غير مألوف.
|
||||
authorization_failed_desc = فشل التفويض لأننا اكتشفنا طلبًا غير صالح. يرجى الاتصال بمشرف التطبيق الذي حاولت ترخيصه.
|
||||
sign_in_openid = المتابعة باستخدام OpenID
|
||||
hint_login = لديك حساب بالفعل؟ <a href="%s">سجّل الدخول الآن!</a>
|
||||
hint_register = يلزمك حساب ؟ <a href="%s">سجِّل الآن.</a>
|
||||
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 = نطاق البريد الإلكتروني للمستخدم <b>%s</b> يتعارض مع قائمة النطاقات المسموحة ، أو الممنوعة. يرجى التأكد من إدخال عنوان البريد الإلكتروني بشكل صحيح.
|
||||
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 = يتم اظهار المستودعات المتعلقة فقط. <a href="%s">أظهر النتائج غير المصفاة</a>.
|
||||
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 = عرض النتائج التي تطابق أي من الكلمات المفتاحية المفصولة بمسافات
|
||||
|
|
|
@ -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.<br>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=<b>@%[1]s</b> hat #%[2]d in %[3]s zusammengeführt.
|
|||
issue.action.approve=<b>@%[1]s</b> hat diesen Pull-Request genehmigt.
|
||||
issue.action.reject=<b>@%[1]s</b> hat Änderungen auf diesem Pull-Request angefordert.
|
||||
issue.action.review=<b>@%[1]s</b> hat diesen Pull-Request kommentiert.
|
||||
issue.action.review_dismissed=<b>@%[1]s</b> hat das letzte Review von %[2]s für diesen Pull-Request verworfen.
|
||||
issue.action.ready_for_review=<b>@%[1]s</b> hat diesen Pull-Request zum Review freigegeben.
|
||||
issue.action.review_dismissed=<b>@%[1]s</b> hat die letzte Sichtung von %[2]s für diesen Pull-Request verworfen.
|
||||
issue.action.ready_for_review=<b>@%[1]s</b> hat diesen Pull-Request für die Sichtung freigegeben.
|
||||
issue.action.new=<b>@%[1]s</b> hat #%[2]d geöffnet.
|
||||
issue.in_tree_path=In %s:
|
||||
|
||||
|
@ -540,8 +540,8 @@ release.new.text=<b>@%[1]s</b> 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 „<a rel="noreferrer" target="_blank" href="%s">WebAuthn</a>“ unterstützen.
|
||||
webauthn_register_key=Sicherheitsschlüssel hinzufügen
|
||||
|
@ -1185,9 +1185,9 @@ blame.ignore_revs=Revisionen in <a href="%s">.git-blame-ignore-revs</a> werden i
|
|||
blame.ignore_revs.failed=Fehler beim Ignorieren der Revisionen in <a href="%s">.git-blame-ignore-revs</a>.
|
||||
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 <a href="%[1]s">%[2]s</a>
|
||||
|
@ -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 <a href="%[2]s">%[3]s</a> geöffnet
|
||||
pulls.merged_by=von <a href="%[2]s">%[3]s</a> 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=<a href="%s">Anmelden</a>, 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 <code>{index}</code> verwendet.
|
||||
settings.tracker_issue_style.regexp_pattern_desc=Die erste gefundene Gruppe wird statt <code>{index}</code> verwendet.
|
||||
settings.tracker_url_format_desc=Du kannst die Platzhalter <code>{user}</code>, <code>{repo}</code>, <code>{index}</code> 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 <code>POST</code>-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=<strong> %d geänderte Dateien</strong> mit <strong>%d neuen</strong> und <strong>%d gelöschten</strong> 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 <a href="%s">die Dokumentation</a> 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 <code>%[2]s</code> nach <code
|
|||
pulls.title_desc_one = möchte %[1]d Commit von <code>%[2]s</code> nach <code id="%[4]s">%[3]s</code> 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 <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht-Token</a> oder einen <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht-Token mit Zugriff auf die Secrets</a>.
|
||||
settings.sourcehut_builds.access_token_helper = Zugangstoken, der die JOBS:RW-Freigabe hat. Generiere auf meta.sr.ht einen <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht-Token</a> oder einen <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht-Token mit Zugriff auf die Geheimnisse</a>.
|
||||
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 <code>%[2]s</code> in <a href="
|
|||
approve_pull_request=`hat <a href="%[1]s">%[3]s#%[2]s</a> genehmigt`
|
||||
reject_pull_request=`schlug Änderungen für <a href="%[1]s">%[3]s#%[2]s</a> vor`
|
||||
publish_release=`veröffentlichte Release <a href="%[2]s">%[4]s</a> in <a href="%[1]s">%[3]s</a>`
|
||||
review_dismissed=`verwarf das Review von <b>%[4]s</b> in <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed=`verwarf die Sichtung von <b>%[4]s</b> in <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||
review_dismissed_reason=Grund:
|
||||
create_branch=legte den Branch <a href="%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a> an
|
||||
starred_repo=favorisierte <a href="%[1]s">%[2]s</a>
|
||||
|
@ -3765,9 +3765,9 @@ conda.registry=Richte diese Registry als Conda-Repository in deiner <code>.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 <code>Package.swift</code> Datei hinzu:
|
||||
swift.install=Füge das Paket deiner <code>Package.swift</code>-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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 = від <a href="%[2]s">%[3]s</a> закрито %[1]s
|
|||
issues.action_check = Поставити/зняти позначку
|
||||
issues.action_check_all = Поставити/зняти позначку з усіх елементів
|
||||
vendored = Сторонній
|
||||
blame.ignore_revs.failed = Не вдалося проігнорувати зміни в <a href="%s">.git-blame-ignore-revs</a>.
|
||||
blame.ignore_revs = Зміни в <a href="%s">.git-blame-ignore-revs</a> ігноруються. Натисніть <a href="%s">тут, щоб обійти це</a> і переглянути авторство у звичайному вигляді.
|
||||
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 = <b>Писати:</b> створювати, оновлювати т
|
|||
issues.read = <b>Читати:</b> дивитись і створювати задачі та коментарі.
|
||||
wiki.read = <b>Читати:</b> переглядати вбудовану вікі та її історію.
|
||||
actions.write = <b>Писати:</b> вручну запускати, перезапускати, скасовувати або схвалювати конвеєри CI/CD в очікуванні.
|
||||
projects.write = <b>Писати:</b> створювати проєкти і стовпчики та редагувати їх.
|
||||
|
||||
[munits.data]
|
||||
pib = ПіБ
|
||||
|
|
|
@ -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": "رؤية ملفك الشخصي تؤثر في قدرة الآخرين على الوصول إلى مستودعاتك غير الخاصة. <a href=\"%s\" target=\"_blank\">اعرف المزيد</a>",
|
||||
"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": "الفروع المطلوب عكسها. اترك الحقل فارغًا لعكس جميع الفروع. راجع توثيق <a href=\"%[1]s\">%[2]s</a> للاطلاع على الصيغة. أمثلة: <code>main, release/*</code>",
|
||||
"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": "لم دمج أي إيداع من <code>%[2]s</code> إلى <code>%[3]s</code> %[4]s",
|
||||
"one": "تم دمج إيداع واحد من <code>%[2]s</code> إلى <code>%[3]s</code> %[4]s",
|
||||
"two": "تم دمج إيداعين اثنين من <code>%[2]s</code> إلى <code>%[3]s</code> %[4]s",
|
||||
"few": "تم دمج %[1]d إيداعات من <code>%[2]s</code> إلى <code>%[3]s</code> %[4]s",
|
||||
"many": "تم دمج %[1]d إيداعاً من <code>%[2]s</code> إلى <code>%[3]s</code> %[4]s",
|
||||
"other": "تم دمج %[1]d إيداعاً من <code>%[2]s</code> إلى <code>%[3]s</code> %[4]s"
|
||||
},
|
||||
"relativetime.months": {
|
||||
"zero": "هذا الشهر",
|
||||
"one": "منذ شهر",
|
||||
"two": "منذ شهرين",
|
||||
"few": "منذ %d أشهر",
|
||||
"many": "منذ %d شهراً",
|
||||
"other": "منذ %d شهراً"
|
||||
},
|
||||
"repo.pulls.title_desc": {
|
||||
"zero": "لا يريد دمج أي إيداع من <code>%[2]s</code> إلى <code id=\"%[4]s\">%[3]s</code>",
|
||||
"one": "يريد دمج إيداع واحد من <code>%[2]s</code> إلى <code id=\"%[4]s\">%[3]s</code>",
|
||||
"two": "يريد دمج إيداعين من <code>%[2]s</code> إلى <code id=\"%[4]s\">%[3]s</code>",
|
||||
"few": "يريد دمج %[1]d إيداعات من <code>%[2]s</code> إلى <code id=\"%[4]s\">%[3]s</code>",
|
||||
"many": "يريد دمج %[1]d إيداعًا من <code>%[2]s</code> إلى <code id=\"%[4]s\">%[3]s</code>",
|
||||
"other": "يريد دمج %[1]d إيداعًا من <code>%[2]s</code> إلى <code id=\"%[4]s\">%[3]s</code>"
|
||||
},
|
||||
"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": "السطر مُزاح بالفعل. اضغط <kbd>Tab</kbd> مرة أخرى أو <kbd>Escape</kbd> لمغادرة المحرر.",
|
||||
"editor.textarea.shift_tab_hint": "لا توجد مسافة بادئة في هذا السطر. اضغط <kbd>Shift</kbd> + <kbd>Tab</kbd> مرة أخرى أو <kbd>Escape</kbd> لمغادرة المحرر.",
|
||||
"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"
|
||||
}
|
||||
|
|
|
@ -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": "Агляд арганізацый"
|
||||
}
|
||||
|
|
|
@ -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 <a href=\"%[1]s\">dokumentaci %[2]s</a>. Příklady: <code>main, release/*</code>"
|
||||
}
|
||||
|
|
|
@ -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 <kbd>Tab</kbd> oder <kbd>Escape</kbd> um den Editor zu verlassen.",
|
||||
"editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals <kbd>Shift</kbd> + <kbd>Tab</kbd> oder <kbd>Escape</kbd> 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 <kbd>Tab</kbd> oder <kbd>Escape</kbd>, um den Editor zu verlassen.",
|
||||
"editor.textarea.shift_tab_hint": "Keine Einrückung auf dieser Zeile. Drücke nochmals <kbd>Shift</kbd> + <kbd>Tab</kbd> oder <kbd>Escape</kbd>, 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. <a href=\"%s\" target=\"_blank\">Erfahre mehr</a>",
|
||||
"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 <a href=\"%[1]s\">„%[2]s“-Dokumentation</a> für die Syntax. Beispiele: <code>main, release/*</code>"
|
||||
}
|
||||
|
|
|
@ -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 <a href=\"%[1]s\">%[2]s</a> documentation for syntax. Examples: <code>main, release/*</code>",
|
||||
"repo.settings.push_mirror.branch_filter.description": "Branches to be mirrored. Leave blank to mirror all branches. See <a href=\"%[1]s\">%[2]s documentation</a> for syntax. Examples: <code>main, release/*</code>",
|
||||
"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 <kbd>Tab</kbd> again or <kbd>Escape</kbd> to leave the editor.",
|
||||
"editor.textarea.shift_tab_hint": "No indentation on this line. Press <kbd>Shift</kbd> + <kbd>Tab</kbd> again or <kbd>Escape</kbd> to leave the editor.",
|
||||
"admin.dashboard.cleanup_offline_runners": "Cleanup offline runners",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"repo.pulls.merged_title_desc": {
|
||||
"one": "isinali ang %[1]d commit mula<code>%[2]s</code> patungong <code>%[3]s</code> %[4]s",
|
||||
"one": "isinali ang %[1]d commit mula <code>%[2]s</code> patungong <code>%[3]s</code> %[4]s",
|
||||
"other": "isinali ang %[1]d mga commit mula sa <code>%[2]s</code> patungong <code>%[3]s</code> %[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 <a href=\"%[1]s\">dokumentasyon ng %[2]s</a> para sa syntax. Halimbawa: <code>main, your-reality, release/*</code>"
|
||||
}
|
||||
|
|
|
@ -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 <a href=\"%[1]s\">%[2]s dokumentācijā</a>. Piemēri: <code>main, release/*</code>",
|
||||
"repo.settings.push_mirror.branch_filter.label": "Zaru atlasītājs (izvēles)"
|
||||
}
|
||||
|
|
|
@ -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 <a href=\"%[1]s\">%[2]s-Dokumenteren</a> för de Syntax. Bispölen: <code>main, release/*</code>",
|
||||
"repo.settings.push_mirror.branch_filter.label": "Twieg-Filter (wenn du willst)"
|
||||
}
|
||||
|
|
|
@ -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 <a href=\"%[1]s\">%[2]s</a> documentatie voor de syntax. Voorbeeld: <code>main, release/*</code>"
|
||||
}
|
||||
|
|
|
@ -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 <a href=\"%[1]s\">%[2]s documentação</a> sobre a sintaxe. Exemplos: <code>main, release/*</code>"
|
||||
}
|
||||
|
|
|
@ -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 <a href=\"%[1]s\">%[2]s documentação</a> sobre a sintaxe. Exemplos: <code>main, release/*</code>",
|
||||
"mail.actions.run_info_sha": "Cometimento: %[1]s"
|
||||
}
|
||||
|
|
|
@ -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": "Синхронизируемые ветви. Оставьте пустым, чтобы синхронизировать все. Ознакомьтесь с синтаксисом в <a href=\"%[1]s\">документации %[2]s</a>. Примеры: <code>main, release/*</code>",
|
||||
"repo.settings.push_mirror.branch_filter.label": "Выбор ветвей (опционально)"
|
||||
}
|
||||
|
|
|
@ -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": "Гілки для дзеркалювання. Залиште порожнім, щоб віддзеркалити всі гілки. Дивіться синтаксис у <a href=\"%[1]s\">документації %[2]s</a>. Приклади: <code>main, release/*</code>",
|
||||
"repo.settings.push_mirror.branch_filter.label": "Фільтр гілок (необов'язково)"
|
||||
}
|
||||
|
|
|
@ -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": "欲镜像的分支。留空以镜像所有分支。关于语法的更多信息,请参见 <a href=\"%[1]s\">%[2]s 文档</a>。例如:<code>main, release/*</code>",
|
||||
"mail.actions.run_info_sha": "提交:%[1]s"
|
||||
}
|
||||
|
|
663
package-lock.json
generated
663
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,476 @@
|
|||
|
||||
|
||||
<!--start release-notes-assistant-->
|
||||
|
||||
## Release notes
|
||||
<!--URL:https://codeberg.org/forgejo/forgejo-->
|
||||
- Breaking security features
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7924): <!--number 7924 --><!--line 0 --><!--description cmVtb3ZlIEFQSSBhdXRoZW50aWNhdGlvbiBtZXRob2RzIHRoYXQgdXNlcyB0aGUgVVJMIHF1ZXJ5-->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).<!--description-->
|
||||
- Security features
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7829): <!--number 7829 --><!--line 0 --><!--description cmVsYXggZW1haWwgcmVxdWlyZW1lbnRz-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7693): <!--number 7693 --><!--line 0 --><!--description Y29uc2lkZXIgV2ViQXV0aG4gJiBTU0ggZm9yIGluc3RhbmNlIHNpZ25pbmc=-->consider WebAuthn & SSH for instance signing.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6897): <!--number 6897 --><!--line 0 --><!--description ZmVhdChzZWMpOiBBZGQgU1NIIHNpZ25pbmcgc3VwcG9ydCBmb3IgaW5zdGFuY2Vz-->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).<!--description-->
|
||||
- Breaking features
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8035): <!--number 8035 --><!--line 0 --><!--description VGhlIGBmb3JnZWpvIGRvY3NgIGNvbW1hbmQgaXMgZGVwcmVjYXRlZCBhbmQgQ0xJIGVycm9ycyBhcmUgbm93IGRpc3BsYXllZCBvbiBzdGRlcnIgaW5zdGVhZCBvZiBzdGRvdXQuIFRoZXNlIGJyZWFraW5nIGNoYW5nZXMgaGFwcGVuZWQgYmVjYXVzZSB0aGUgcGFja2FnZSB1c2VkIHRvIHBhcnNlIHRoZSBjb21tYW5kIGxpbmUgYXJndW1lbnRzIHdhcyBbdXBncmFkZWQgZnJvbSB2MiB0byB2M10oaHR0cHM6Ly9jbGkudXJmYXZlLm9yZy9taWdyYXRlLXYyLXRvLXYzLykuIEEgW3NlcGFyYXRlIHByb2plY3Qgd2FzIGluaXRpYXRlZF0oaHR0cHM6Ly9naXRodWIuY29tL3VyZmF2ZS9jbGktZG9jcykgdG8gcmUtaW1wbGVtZW50IHRoZSBgZG9jc2AgY29tbWFuZCwgYnV0IGl0IGlzIG5vdCB5ZXQgcHJvZHVjdGlvbiByZWFkeS4=-->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.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7745): <!--number 7745 --><!--line 0 --><!--description cmVtb3ZlIHRoZSBsZWdhY3kgYFRFU1RfQ09ORkxJQ1RJTkdfUEFUQ0hFU19XSVRIX0dJVF9BUFBMWWAgc2V0dGluZw==-->remove the legacy `TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY` setting<!--description-->
|
||||
- Breaking bug fixes
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8139): <!--number 8139 --><!--line 0 --><!--description QVBJOiBlbmZvcmNlIHNoYSByZXF1aXJlbWVudCBvbiBgUE9TVCAvcmVwb3Mve293bmVyfS97cmVwb30vY29udGVudHNg-->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.<!--description-->
|
||||
- User Interface features
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8185): <!--number 8185 --><!--line 0 --><!--description ZmVhdCh1aSk6IGZlZGl2ZXJzZSBoYW5kbGUgbWFya3VwIHZpYSByZWRpcmVjdCBzZXJ2ZXI=-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8121): <!--number 8121 --><!--line 0 --><!--description YWRkIHVzZXIgdmlzaWJpbGl0eSBkZXNjcmlwdGlvbiBpbiBzZXR0aW5ncyBwYWdl-->add user visibility description in the settings page.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8111): <!--number 8111 --><!--line 0 --><!--description YWRkIG1vZGVsIHZpZXdlciBmb3IgYC5nbGJgIChHTFRGKSBtb2RlbCBpbiBmaWxlIHZpZXc=-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7998): <!--number 7998 --><!--line 0 --><!--description ZmVhdCh1aSk6IHNob3cgc2l6ZSBjb25zdHJhaW50cyBvZiBjdXN0b20gYXZhdGFy-->show size constraints of custom avatar.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7992): <!--number 7992 --><!--line 0 --><!--description ZmVhdCh1aSk6IGFkZCBsaW5rcyB0byBtaWxlc3RvbmVzIGFuZCBwcm9qZWN0cyBpbiBpc3N1ZSBjb21tZW50cw==-->add links to milestones and projects in issue comments.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7958): <!--number 7958 --><!--line 0 --><!--description ZmVhdCh1aSk6IGdsb2JhbCBzdHlsaW5nIGZvciBrYmQgdGFn-->global styling for the kbd tag.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7947): <!--number 7947 --><!--line 0 --><!--description ZmVhdCh1aSk6IGhpbnRzIGluIGVtcHR5IHVzZXJjYXJkcyBsaXN0cw==-->hints in empty usercards lists.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7906): <!--number 7906 --><!--line 0 --><!--description ZmVhdCh1aSk6IHJlZGVzaWduIHVzZXIgcHJvZmlsZSBhY3Rpb25zIGxheW91dA==-->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.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7531): <!--number 7531 --><!--line 0 --><!--description ZmVhdCh1aSk6IGltcHJvdmUgZGVzYyBpbiBQYWNrYWdlcyBzZXR0aW5ncw==-->improve the description in the packages settings.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7516): <!--number 7516 --><!--line 0 --><!--description aW5saW5lIHB1YmxpYyBzc2gga2V5IGluIHZlcmlmaWNhdGlvbiBjb21tYW5k-->inline public ssh key in verification command.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7481): <!--number 7481 --><!--line 0 --><!--description ZmVhdCh1aSk6IHVzZSBzd2l0Y2ggZWxlbWVudCBmb3IgbWFya2Rvd24gZWRpdG9yIG1vZGVz-->use switch element for markdown editor modes.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7388): <!--number 7388 --><!--line 0 --><!--description ZmVhdCh1aSk6IG1ha2UgSlMgYXNzZXQgbG9hZCBlcnJvciBtZXNzYWdlIHRyYW5zbGF0YWJsZQ==-->make JS asset load error message translatable.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7385): <!--number 7385 --><!--line 0 --><!--description VXNlIGBnaXQgc3dpdGNoIC1jYCBpbnN0ZWFkIG9mIGBnaXQgY2hlY2tvdXQgLWJg-->improve performances by using `git switch -c` instead of `git checkout -b`.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7377): <!--number 7377 --><!--line 0 --><!--description ZmVhdCh1aS9taWdyYXRpb25zKTogY2xhcmlmeSBkZXNpcmVkIGF1dG9jb21wbGV0aW9uIHR5cGUgZm9yIGNsb25lX2FkZHI=-->clarify the desired autocompletion type for the clone address in migrations.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7373): <!--number 7373 --><!--line 0 --><!--description TWlncmF0aW9ucyBVSTogSW1wcm92ZSBDbGFyaXR5IGZvciBNaWdyYXRpb24gRGVzY3JpcHRpb24gVGV4dGFyZWE=-->improve the clarity of the migration description textarea.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7361): <!--number 7361 --><!--line 0 --><!--description ZmVhdCh1aSk6IEF1dG9tYXRpY2FsbHkgcmVmcmVzaCB3b3JrZmxvd3MgaW4gdGhlICJBY3Rpb25zIiBsaXN0-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7274): <!--number 7274 --><!--line 0 --><!--description dWk6IGltcHJvdmUgZXJyb3IgcGFnZXM=-->improve error pages.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7155): <!--number 7155 --><!--line 0 --><!--description ZmVhdCh1aSk6IGltcHJvdmUgdGhlIHVzZXIgZXhwZXJpZW5jZSB0byByZXZpZXcgaW5kaXZpZHVhbCBjb21taXRzIGluIGEgcHVsbCByZXF1ZXN0-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7128): <!--number 7128 --><!--line 0 --><!--description VXNlIGF2YWlsYWJsZSBzY3JlZW4gd2lkdGggZm9yIEFjdGlvbnMgbG9ncw==-->use the available screen width when displaying Forgejo Actions logs.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6933): <!--number 6933 --><!--line 0 --><!--description U2hvdyBpZiBjb21taXQgaXMgdmVyaWZpZWQgaW4gYWN0aXZpdHkgZmVlZCBvZiBhbiB1c2VyIG9yIGFuIG9yZ2FuaXphdGlvbiBmb3IgbmV3IGFjdGl2aXR5-->show if a commit is verified in the activity feed of a user or an organization.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6813): <!--number 6813 --><!--line 0 --><!--description UmVpbXBsZW1lbnRlZCBlZGl0b3IgVGFiIGtleSBoYW5kbGluZyB3aXRoIGFjY2Vzc2liaWxpdHkgc2FmZWd1YXJkcy4gQmFsYW5jZSBoYXZpbmcgdGhlIGVkaXRvciB3b3JrIGFzIGV4cGVjdGVkIGJ5IGRldmVsb3BlcnMgKHdpdGggVGFiIGtleSBhZmZlY3RpbmcgaW5kZW50YXRpb24pIHdoaWxlIGFsc28gbm90IGltcGVkaW5nIGtleWJvYXJkIG5hdmlnYXRpb24u-->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)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6795): <!--number 6795 --><!--line 0 --><!--description ZmVhdCh1aSk6IHJlZGVzaWduIG1pZ3JhdGlvbiBzZWxlY3Rpb24gc2NyZWVu-->redesign the migration selection page.<!--description-->
|
||||
- User Interface bug fixes
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8417) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8514)): <!--number 8514 --><!--line 0 --><!--description Zml4KHVpKTogbXVsdGlwbGUgQ29tYm9NYXJrZG93bkVkaXRvcnMgb24gb25lIHBhZ2UgaW50ZXJmZXJl-->multiple ComboMarkdownEditors on one page interfere with each other.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7749) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8362)): <!--number 8362 --><!--line 0 --><!--description Zml4KHVpKTogQWRkIHBhc3RlZCBpbWFnZXMgdG8gZHJvcHpvbmU=-->pasting images into the comment editor will now show that image in the ‘dropzone’.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8296) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8317)): <!--number 8317 --><!--line 0 --><!--description Zml4OiBhZGQgbWlzc2luZyB0cnVzdCBzdGF0dXMgdG8gcHVsbCByZXZpZXcgY29tbWl0cw==-->add missing trust status to pull review commits.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8246) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8282)): <!--number 8282 --><!--line 0 --><!--description Zml4KHVpKTogYWRkIG1pc3NpbmcgbGF6eSBsb2FkIGF0dHJpYnV0ZSB0byBpbWFnZXM=-->add missing lazy load attribute to images.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8067): <!--number 8067 --><!--line 0 --><!--description cG9ydChnaXRlYSk6IFJldGFpbiBpc3N1ZS9wdWxsIHNvcnQgdHlwZQ==-->retain sort type when viewing issue or pull requests.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7893): <!--number 7893 --><!--line 0 --><!--description Zml4KHVpKTogaW5jbHVkZSBlbm91Z2ggYWN0aXZpdHkgZm9yIHRoZSBlbnRpcmUgaGVhdG1hcA==-->include enough activity for the entire heatmap.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7726): <!--number 7726 --><!--line 0 --><!--description U2hvdyB3YXJuaW5nIGluIGxvY2tlZCBpc3N1ZSBkaXNjdXNzaW9u-->show warning in locked issue discussion.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7492): <!--number 7492 --><!--line 0 --><!--description Zml4KHVpKTogZW5zdXJlIGNvbnNpc3RlbnQgc3dpdGNoIHBvc2l0aW9uIGluIG1hcmtkb3duIGVkaXRvcg==-->ensure consistent switch position in the markdown editor.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7420): <!--number 7420 --><!--line 0 --><!--description Zml4KHVpKTogZGlzcGxheSB1c2VyLWZyaWVuZGx5IG1lc3NhZ2UgZm9yIHJhbmdlIGVycm9y-->display user-friendly message for range error.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7402): <!--number 7402 --><!--line 0 --><!--description Zml4KHVpKTogbWFrZSBsaW1pdHMgY2xlYXJlciBpbiBjcmVhdGUgcmVwbyBmb3Jt-->make limits clearer in the create repository form.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7307): <!--number 7307 --><!--line 0 --><!--description RG9uJ3QgcHV0IHRyYWlsaW5nIHNsYXNoIGluIGF1dG9nZW5lcmF0ZWQgbmFtZSBkdXJpbmcgaW1wb3J0-->don't put trailing slash in autogenerated name in the migration form.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7245): <!--number 7245 --><!--line 0 --><!--description YWxsb3cgdXNlciB3aXRoIGFjdGlvbnMgd3JpdGUgcGVybWlzc2lvbiB0byBydW4gYSB3b3JrZmxvdyBmcm9tIHRoZSB3ZWIgVUk=-->allow user with actions write permission to run a workflow from the web UI.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6799): <!--number 6799 --><!--line 0 --><!--description Zml4KHVpKTogZW5zdXJlIHNhbWUgd2lkdGggb2YgdXNlcmNhcmRzIGluIGdyaWQ=-->ensure usercards in grid have the same width.<!--description-->
|
||||
- Localization
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8238) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8294)): <!--number 8294 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8178): <!--number 8178 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8077): <!--number 8077 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7969): <!--number 7969 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7895): <!--number 7895 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7819): <!--number 7819 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7742): <!--number 7742 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7637): <!--number 7637 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7572): <!--number 7572 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7507): <!--number 7507 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7438): <!--number 7438 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7363): <!--number 7363 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7275): <!--number 7275 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- Features
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8179): <!--number 8179 --><!--line 0 --><!--description QVBJOiBuZXcgYEdFVCAvcmVwb3Mve293bmVyfS97cmVwb30vZ2l0L2Jsb2JzYCBlbmRwb2ludCB0byByZXRyaWV2ZSBtdWx0aXBsZSBibG9icyBhdCBvbmNl-->new `GET /repos/{owner}/{repo}/git/blobs` API endpoint to retrieve multiple blobs at once.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8177): <!--number 8177 --><!--line 0 --><!--description YWx3YXlzIHB1Ymxpc2ggdGhlIGxpbmsgdG8gdGhlIGNvbW1pdCBzdGF0dXM=-->always publish the link to the commit status.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8143): <!--number 8143 --><!--line 0 --><!--description aW1wcm92ZSBnZW5lcmF0aW9uIG9mIGJ1bmRsZWQgYXNzZXRz-->improve the performances of the generation of bundled assets.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8115): <!--number 8115 --><!--line 0 --><!--description ZW5hYmxlIGBtbGtlbTc2OHgyNTUxOS1zaGEyNTZgIGJ5IGRlZmF1bHQgZm9yIGJ1aWx0aW4gc3No-->enable `mlkem768x25519-sha256` by default for builtin ssh.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8070): <!--number 8070 --><!--line 0 --><!--description c3VwcG9ydCBhcnRpZmFjdCB1cGxvYWRzIGZvciBPQ0kgY29udGFpbmVyIHBhY2thZ2Vz-->support artifact uploads for OCI container packages.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8047): <!--number 8047 --><!--line 0 --><!--description YWRkIGBhZG1pbiB1c2VyIHJlc2V0LW1mYWAgQ0xJIGNvbW1hbmQ=-->add `admin user reset-mfa` CLI command.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7988): <!--number 7988 --><!--line 0 --><!--description dXBkYXRlIGFtYmlnaW91cyBjaGFyYWN0ZXJz-->update the list of ambigious characters.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7986): <!--number 7986 --><!--line 0 --><!--description bWFrZSBGb3JnZWpvIEFjdGlvbnMgc2VydmVyIGxvZ3MgbGVzcyBub2lzeQ==-->make Forgejo Actions server logs less noisy.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7968): <!--number 7968 --><!--line 0 --><!--description QWxsb3cgc2VhcmNoaW5nIGlzc3VlcyBieSBudW1iZXIsIHByaW9yaXRpemUgdGl0bGUgbWF0Y2hlcyB3aGVuIHNvcnRlZCBieSByZWxldmFuY2U=-->allow searching issues by number, prioritize title matches when sorted by relevance.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7953): <!--number 7953 --><!--line 0 --><!--description cmVwbGFjZSBnby1ycG11dGlscyBsaWJyYXJ5IHdpdGggb3VyIG93bg==-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7902): <!--number 7902 --><!--line 0 --><!--description Y29uZmlndXJhYmxlIGRlZmF1bHQgdW5pdHMgZm9yIG1pcnJvcnM=-->configurable default units for mirrors.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7896): <!--number 7896 --><!--line 0 --><!--description ZW5oOiBhbGxvdyBwZXIgcmVwbyBpc3N1ZSByZWluZGV4aW5nIGZvciBhZG1pbnM=-->a repository administrator has control over reindexing the issues.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7803): <!--number 7803 --><!--line 0 --><!--description YXV0byBjbGVhbnVwIG9mIG9mZmxpbmUgcnVubmVycw==-->auto cleanup of offline runners.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7727): <!--number 7727 --><!--line 0 --><!--description aW1wcm92ZWQgcGVyZm9ybWFuY2VzIHdoZW4gY2hlY2tpbmcgZm9yIGNvbmZsaWN0cyBvbiBwdWxsIHJlcXVlc3Rz-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7716): <!--number 7716 --><!--line 0 --><!--description YWxsb3cgYWNjZXNzIHRvIGAvYXBpL3YxL3BhY2thZ2VzL3t1c2VybmFtZX1gIHdpdGhvdXQgdG9rZW4=-->allow access to publicly available `/api/v1/packages/{username}` without a token.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7699): <!--number 7699 --><!--line 0 --><!--description aW1wbGVtZW50IGBHRVQgL3JlcG9zL3tvd25lcn0ve3JlcG99L2FjdGlvbnMvcnVuc2AgYW5kIGBHRVQgL3JlcG9zL3tvd25lcn0ve3JlcG99L2FjdGlvbnMvcnVucy97cnVuX2lkfWA=-->implement the `GET /repos/{owner}/{repo}/actions/runs` and `GET /repos/{owner}/{repo}/actions/runs/{run_id}` API endpoints.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7527): <!--number 7527 --><!--line 0 --><!--description dXNlIGdpdC1yZXBsYXkgZm9yIHJlYmFzaW5n-->use git-replay for rebasing for better performances.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7509): <!--number 7509 --><!--line 0 --><!--description c2VuZCBtYWlsIG9uIGZhaWxlZCBvciByZWNvdmVyZWQgRm9yZ2VqbyBBY3Rpb25zIHJ1bg==-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7508): <!--number 7508 --><!--line 0 --><!--description QWN0aW9ucyBGYWlsdXJlLCBTdWNjZXNzLCBSZWNvdmVyIFdlYmhvb2tz-->Forgejo Actions failure, success, recover webhooks.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7418): <!--number 7418 --><!--line 0 --><!--description YWRkIGBsYXN0X2NvbW1pdF93aGVuYCB0byBjb250ZW50cyByZXNwb25zZQ==-->add `last_commit_when` to API contents responses.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7387): <!--number 7387 --><!--line 0 --><!--description aW5jbHVkZSBhIGRlZmF1bHQgcm9ib3RzLnR4dCB0byByZWR1Y2UgdGhlIGltcGFjdCBvZiBjcmF3bGVycw==-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7212): <!--number 7212 --><!--line 0 --><!--description dXNlIFhPUk0gRW5naW5lR3JvdXAgaW5zdGVhZCBvZiBzaW5nbGUgRW5naW5lIGNvbm5lY3Rpb24=-->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).<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2364): <!--number 2364 --><!--line 0 --><!--description c3luYyBmb3Jrcw==-->sync forks. [Read more in the v12.0 companion blog post](https://forgejo.org/2025-07-release-v12-0/#keeping-forks-in-sync).<!--description-->
|
||||
- Bug fixes
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8511) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8516)): <!--number 8516 --><!--line 0 --><!--description Zml4OiBQUiBub3QgYmxvY2tlZCBieSByZXZpZXcgcmVxdWVzdCBmb3IgYSB3aGl0ZWxpc3RlZCB0ZWFt-->pull requests were not blocked by review request for a whitelisted team.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8475) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8480)): <!--number 8480 --><!--line 0 --><!--description c2V2ZXJhbCBmaXhlcyBvZiBBTFQgUGFja2FnZSByZWdpc3RyeQ==-->several fixes of the ALT RPM package registry.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8391) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8459)): <!--number 8459 --><!--line 0 --><!--description QXV0aCBIZWFkZXI6IEFsbG93IGxvd2VyY2FzZSBhcyB3ZWxsIGFzIHVwcGVyY2FzZSB0b2tlbg==-->allow lowercase as well as uppercase token keyword in the auth header.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8450) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8454)): <!--number 8454 --><!--line 0 --><!--description Zml4OiBjb3JyZWN0bHkgbWFyayByZXZpZXdzIGFzIHN0YWxlIGZvciBBR2l0IFBScw==-->correctly mark reviews as stale for AGit pull requests.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8367) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8386)): <!--number 8386 --><!--line 0 --><!--description Zml4OiB1c2VyIGFjdGl2YXRpb24gd2l0aCB1cHBlcmNhc2UgZW1haWwgYWRkcmVzcw==-->user activation failed when an email address contained uppercase letters.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8330) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8349)): <!--number 8349 --><!--line 0 --><!--description Zml4OiBsb2FkIE9sZE1pbGVzdG9uZSBiYXNlZCBvbiBPbGRNaWxlc3RvbmVJRCwgbm90IE1pbGVzdG9uZUlE-->fix: load OldMilestone based on OldMilestoneID, not MilestoneID<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8037): <!--number 8037 --><!--line 0 --><!--description b21pdCBDb250ZW50LUxlbmd0aCBvbiAzMDcgcmVkaXJlY3RzIHdoZW4gc2VydmluZyBkaXJlY3QgbWFuaWZlc3QgZm9yIGNvbnRhaW5lcnM=-->omit Content-Length on 307 redirects when serving direct manifest for containers.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8034): <!--number 8034 --><!--line 0 --><!--description Y2FtZWwgYW5kIHBhc2NhbCBjYXNlIHRyYW5zZm9ybWVy-->fix a bug causing the PASCAL-modifier to return camel-case.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8028): <!--number 8028 --><!--line 0 --><!--description QWRkcyBjb2RlIHRvIHJlbW92ZSB0aGUgdHJhaWxpbmcgc2xhc2ggZnJvbSB0aGUgaXNzdWVyIGluIG9hdXRoIGNsYWltcw==-->remove the trailing slash from the issuer in OAuth claims.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8025): <!--number 8025 --><!--line 0 --><!--description cmV0dXJuIHRoZSBjb3JyZWN0IGFnaXQgdHlwZSBpbiBzc2hfaW5mbw==-->return the correct AGit type in ssh_info.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7932): <!--number 7932 --><!--line 0 --><!--description W2dpdGVhXSBGaXggdXJsIHZhbGlkYXRpb24gaW4gd2ViaG9vayBhZGQvZWRpdCBBUEk=-->fix url validation in the webhook add/edit API.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7930): <!--number 7930 --><!--line 0 --><!--description QWRkIGVycm9yIHJlcG9ydGluZyB0byBQUnMgd2l0aCBpbnZhbGlkIHdvcmtmbG93cw==-->add error reporting to pull requests with invalid Forgejo Actions workflow files.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7644): <!--number 7644 --><!--line 0 --><!--description YWxsb3cgaW5zdGFuY2UgQVBJIFVSTHMgaW4gcmVsZWFzZSBhc3NldHM=-->allow instance API URLs in release assets.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7604): <!--number 7604 --><!--line 0 --><!--description aW1wcm92ZSBkYXNoYm9hcmQgbG9hZGluZyBwZXJmb3JtYW5jZXM=-->improve the dashboard loading performances.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7454): <!--number 7454 --><!--line 0 --><!--description Q2FuY2VsIGEgcmV2aWV3-->fix a border case where it was not possible to cancel a pull request review.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7409): <!--number 7409 --><!--line 0 --><!--description Zml4IGFjbWUgcmVuZXdhbA==-->fix acme renewal.<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6352): <!--number 6352 --><!--line 0 --><!--description bWlncmF0ZSBNYXZlbiBwYWNrYWdlcyB0byAiZ3JvdXBJZDphcnRpZmFjdElkIiBuYW1lIGNvbmNhdGVuYXRpb24sIHJlZ2VuZXJhdGUgbWV0YWRhdGEgYW5kIGZpeCBtaXNzaW5nIGdyb3VwSWQ=-->migrate Maven packages to "groupId:artifactId" name concatenation, regenerate metadata and fix missing groupId.<!--description-->
|
||||
- Included for completeness but not worth a release note
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8534): <!--number 8534 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->i18n: update of translations from Codeberg Translate<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8530) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8532)): <!--number 8532 --><!--line 0 --><!--description Zml4KHBhY2thZ2VzKTogc2tpcCBhbm90aGVyIHN0YWNrIGZyYW1lIGZyb20gbG9nZ2luZw==-->fix(packages): skip another stack frame from logging<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8527) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8528)): <!--number 8528 --><!--line 0 --><!--description Zml4OiBpZ25vcmUgIkNsb3NlIiBlcnJvciB3aGVuIHVwbG9hZGluZyBjb250YWluZXIgYmxvYg==-->fix: ignore "Close" error when uploading container blob<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8524) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8526)): <!--number 8526 --><!--line 0 --><!--description Y2hvcmU6IGZhaWxlZCBhdXRoZW50aWNhdGlvbiBhdHRlbXB0cyBhcmUgbm90IGVycm9ycyBhbmQgYXJlIGRpc3BsYXllZCBhdCB0aGUgbG9nIGluZm8gbGV2ZWw=-->chore: failed authentication attempts are not errors and are displayed at the log info level<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8519) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8523)): <!--number 8523 --><!--line 0 --><!--description Zml4OiBleHBhbmRpbmcgZXhhY3RseSAyMCBsaW5lcyBiZXR3ZWVuIGRpZmYgc2VjdGlvbnMgbGVhdmVzIHZpc3VhbCBhcnRpZmFjdA==-->fix: expanding exactly 20 lines between diff sections leaves visual artifact<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8301) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8518)): <!--number 8518 --><!--line 0 --><!--description Y2hvcmU6IHVzZSBldmVudHVhbGx5IGZvciBteXNxbCBjb2xsYXRpb24gdGVzdA==-->chore: use eventually for mysql collation test<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8492) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8498)): <!--number 8498 --><!--line 0 --><!--description Zml4KGNvZGUtc2VhcmNoKTogSGlnaGxpZ2h0U2VhcmNoUmVzdWx0Q29kZSBzaG91bGQgY291bnQgdGhlIG51bWJlciBvZiBieXRlcyBhbmQgbm90IHRoZSBudW1iZXIgb2YgcnVuZXM=-->fix(code-search): HighlightSearchResultCode should count the number of bytes and not the number of runes<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8464) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8474)): <!--number 8474 --><!--line 0 --><!--description Zml4OiB1c2UgcGFyZW50IGNvbnRleHQgZm9yIG5ldyB0cmFuc2FjdGlvbnM=-->fix: use parent context for new transactions<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8460) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8466)): <!--number 8466 --><!--line 0 --><!--description Y2hvcmU6IGRpc2FibGUgbWlzbWF0Y2hlZCByb290IFVSTCBlMmUgdGVzdCBmb3Igc2FmYXJp-->chore: disable mismatched root URL e2e test for safari<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8461) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8463)): <!--number 8463 --><!--line 0 --><!--description Y2hvcmU6IGRvIG5vdCBuYXZpZ2F0ZSB0byBzYW1lIFVSTCBpbiBFMkUgdGVzdA==-->chore: do not navigate to same URL in E2E test<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8448) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8455)): <!--number 8455 --><!--line 0 --><!--description Zml4KGVtYWlsKTogYWN0aW9ucyBub3RpZmljYXRpb24gdGVtcGxhdGUgY29uZnVzZXMgYnJhbmNoIHdpdGggUFI=-->fix(email): actions notification template confuses branch with PR<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8258) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8439)): <!--number 8439 --><!--line 0 --><!--description Zml4OiBjb3JydXB0ZWQgd2lraSB1bml0IGRlZmF1bHQgcGVybWlzc2lvbiAoIzgyMzQgZm9sbG93LXVwKQ==-->fix: corrupted wiki unit default permission (#8234 follow-up)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8366) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8404)): <!--number 8404 --><!--line 0 --><!--description Zml4OiBjYW5jZWxsZWQgb3Igc2tpcHBlZCBydW5zIGFyZSBub3QgZmFpbHVyZXMgZm9yIG5vdGlmaWNhdGlvbnM=-->fix: cancelled or skipped runs are not failures for notifications<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8400) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8402)): <!--number 8402 --><!--line 0 --><!--description Y2hvcmU6IGltcHJvdmUgcmVsaWFiaWxpdHkgb2Ygd2ViYXV0aG4gZTJlIHRlc3Q=-->chore: improve reliability of webauthn e2e test<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8261) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8398)): <!--number 8398 --><!--line 0 --><!--description Zml4OiBza2lwIGVtcHR5IHRva2VucyBpbiBTZWFyY2hPcHRpb25zLlRva2Vucygp-->fix: skip empty tokens in SearchOptions.Tokens()<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8374) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8390)): <!--number 8390 --><!--line 0 --><!--description Zml4OiBkaXNhYmxlIEZvcmdlam8gQWN0aW9ucyBlbWFpbCBub3RpZmljYXRpb25zIG9uIHJlY292ZXJ5-->fix: disable Forgejo Actions email notifications on recovery<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8326) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8331)): <!--number 8331 --><!--line 0 --><!--description Zml4OiBtYWtlIEFQSSAvcmVwb3Mve293bmVyfS97cmVwb30vY29tcGFyZS97YmFzZWhlYWR9IHdvcmsgd2l0aCBmb3Jrcw==-->fix: make API /repos/{owner}/{repo}/compare/{basehead} work with forks<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8320) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8321)): <!--number 8321 --><!--line 0 --><!--description Y2hvcmU6IHNvcnQgYmxvY2tlZCB1c2VycyBsaXN0IGZvciBkZXRlcm1pc3RpYyByZXN1bHRz-->chore: sort blocked users list for determistic results<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8267) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8319)): <!--number 8319 --><!--line 0 --><!--description Zml4OiBhYnVzZSByZXBvcnRzIHN0cmluZyBkYXRhIHR5cGVz-->fix: abuse reports string data types<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8304) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8318)): <!--number 8318 --><!--line 0 --><!--description Zml4OiBwYXNzIGRvZXIncyBJRCBmb3IgQ1JVRCBpbnN0YW5jZSBzaWduaW5n-->fix: pass doer's ID for CRUD instance signing<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8002) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8290)): <!--number 8290 --><!--line 0 --><!--description Zml4KHVpKTogcmVsZWFzZTogbmFtZSBpcyBvdmVycmlkZGVuIHdpdGggdGFnIG5hbWUgb24gZWRpdA==-->fix(ui): release: name is overridden with tag name on edit<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8286) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8288)): <!--number 8288 --><!--line 0 --><!--description UmV2ZXJ0ICJmaXgoYXBpKTogZG9jdW1lbnQgYGlzX3N5c3RlbV93ZWJob29rYCBmaWVsZCAoIzc3ODQpIg==-->Revert "fix(api): document `is_system_webhook` field (#7784)"<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8271) ([backported](https://codeberg.org/forgejo/forgejo/pulls/8277)): <!--number 8277 --><!--line 0 --><!--description Q0kgZGVidWc6IHRlc3RTbGVlcDogc2hvdyBhY3R1YWwgdGltZXMgb24gZmFpbHVyZXM=-->CI debug: testSleep: show actual times on failures<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8268): <!--number 8268 --><!--line 0 --><!--description Y2hvcmU6IHVwZGF0ZSBzZWN1cml0eSBvcHRpb24gaW4gaXNzdWUgdGVtcGxhdGVz-->chore: update security option in issue templates<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8260): <!--number 8260 --><!--line 0 --><!--description VG9rZW4uUGFyc2VJc3N1ZVJlZmVyZW5jZSBjcmFzaGluZyBvbiBlbXB0eSBzdHJpbmc=-->Token.ParseIssueReference crashing on empty string<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8256): <!--number 8256 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHY0MS4xLjQgKGZvcmdlam8p-->Update renovate to v41.1.4 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8253): <!--number 8253 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHY0MSAoZm9yZ2VqbykgKG1ham9yKQ==-->Update renovate to v41 (forgejo) (major)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8252): <!--number 8252 --><!--line 0 --><!--description YWRkIGFuIGluZGV4IHRvIHRoZSBBY3Rpb25SdW4uc3RvcHBlZCBjb2x1bW4=-->add an index to the ActionRun.stopped column<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8250): <!--number 8250 --><!--line 0 --><!--description YnVnOiB1bmlmeSBSZXBvQWN0aW9uUnVuIGFuZCBBY3Rpb25SdW4gc3RydWN0cw==-->bug: unify RepoActionRun and ActionRun structs<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8248): <!--number 8248 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLWNoaS9jaGkvdjUgdG8gdjUuMi4yIChmb3JnZWpvKQ==-->Update module github.com/go-chi/chi/v5 to v5.2.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8245): <!--number 8245 --><!--line 0 --><!--description RG93bmdyYWRlIHBsYXl3cmlnaHQgdGVtcG9yYXJpbHkgYW5kIGFsbG93IHJ1bm5pbmcgYWxsIGUyZSB0ZXN0cw==-->Downgrade playwright temporarily and allow running all e2e tests<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8243): <!--number 8243 --><!--line 0 --><!--description Z2l0L2Jsb2IgdXNlIE5ld1RydW5jYXRlZFJlYWRlciBmb3IgcHJvZmlsZSBhbmQgY29kZW93bmVycw==-->git/blob use NewTruncatedReader for profile and codeowners<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8242): <!--number 8242 --><!--line 0 --><!--description YnVnOiBGb3JnZWpvIEFjdGlvbnMgZW1haWwgbm90aWZpY2F0aW9ucyBhcmUgb3B0LWlu-->bug: Forgejo Actions email notifications are opt-in<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8236): <!--number 8236 --><!--line 0 --><!--description cHJldmVudCA1MDAgbWVzc2FnZSBvbiBpbnZhbGlkIHVzZXJuYW1l-->prevent 500 message on invalid username<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8227): <!--number 8227 --><!--line 0 --><!--description b25seSBzZW5kIEZvcmdlam8gQWN0aW9ucyBub3RpZmljYXRpb25zIHRvIG9uZSB1c2Vy-->only send Forgejo Actions notifications to one user<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8226): <!--number 8226 --><!--line 0 --><!--description Y2hvcmU6IHNvcnQgbWFpbGVyIG1lc3NhZ2VzIGluIHRlc3QgYXNzZXJ0aW9u-->chore: sort mailer messages in test assertion<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8224): <!--number 8224 --><!--line 0 --><!--description Y2hvcmUocmVsZWFzZS1ub3Rlcyk6IEZvcmdlam8gdjExLjAuMg==-->chore(release-notes): Forgejo v11.0.2<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8223): <!--number 8223 --><!--line 0 --><!--description YmxvYjogR2V0QmxvYkNvbnRlbnQ6IHJlZHVjZSBhbGxvY2F0aW9ucw==-->blob: GetBlobContent: reduce allocations<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8220): <!--number 8220 --><!--line 0 --><!--description Zml4KHRlc3RzKTogVGVzdEluaXRJbnN0cnVjdGlvbnMgbXVzdCB1c2UgZm9yRWFjaE9iamVjdEZvcm1hdA==-->fix(tests): TestInitInstructions must use forEachObjectFormat<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8219): <!--number 8219 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb2RlLmZvcmdlam8ub3JnL2Zvcmdlam8vYWN0IHRvIHYxLjI4LjAgKGZvcmdlam8p-->Update module code.forgejo.org/forgejo/act to v1.28.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8218): <!--number 8218 --><!--line 0 --><!--description VXBkYXRlIGRhdGEuZm9yZ2Vqby5vcmcvb2NpL2FscGluZSBEb2NrZXIgdGFnIHRvIHYzLjIyIChmb3JnZWpvKQ==-->Update data.forgejo.org/oci/alpine Docker tag to v3.22 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8217): <!--number 8217 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21pbmlvL21pbmlvLWdvL3Y3IHRvIHY3LjAuOTQgKGZvcmdlam8p-->Update module github.com/minio/minio-go/v7 to v7.0.94 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8216): <!--number 8216 --><!--line 0 --><!--description Y2hvcmU6IG1pZ3JhdGUgdG8gYEBzdHlsaXN0aWMvZXNsaW50LXBsdWdpbmA=-->chore: migrate to `@stylistic/eslint-plugin`<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8215): <!--number 8215 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZXNsaW50LXBsdWdpbi13YyB0byB2MyAoZm9yZ2Vqbyk=-->Update dependency eslint-plugin-wc to v3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8214): <!--number 8214 --><!--line 0 --><!--description Zml4KHVpKTogaXNzdWUgY29tbWVudCBhbmNob3Igb24gdGltZSBzdGFtcA==-->fix(ui): issue comment anchor on time stamp<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8209): <!--number 8209 --><!--line 0 --><!--description Z2l0X21vZGVsLkNvbW1pdFN0YXR1c2VzSGlkZUFjdGlvbnNVUkwgaXMgb2Jzb2xldGU=-->git_model.CommitStatusesHideActionsURL is obsolete<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8207): <!--number 8207 --><!--line 0 --><!--description UmVtb3ZlIDFtcyBkZWxheSBiZWZvcmUgaW5zZXJ0aW5nIGxpc3QgcHJlZml4LCBmaXggcmFjZSBjb25kaXRpb24gaW4gdGVzdHM=-->Remove 1ms delay before inserting list prefix, fix race condition in tests<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8205): <!--number 8205 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSBnb3BscyBpbiBNYWtlZmlsZQ==-->chore: remove gopls in Makefile<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8202): <!--number 8202 --><!--line 0 --><!--description ZG8gbm90IGNoZWNrIGZvciBgb2JqZWN0X2Zvcm1hdF9uYW1lYCBmaWVsZA==-->do not check for `object_format_name` field<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8199): <!--number 8199 --><!--line 0 --><!--description ZmVhdCh1aSk6IHVzZSBrYmQgaW4gbGFiZWwgc2VsZWN0b3IgaGludCwgcmVtb3ZlIGVudGVy-->feat(ui): use kbd in label selector hint, remove enter<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8198): <!--number 8198 --><!--line 0 --><!--description W2dpdGVhXSB3ZWVrIDIwMjUtMjIgY2hlcnJ5IHBpY2sgKGdpdGVhL21haW4gLT4gZm9yZ2Vqbyk=-->[gitea] week 2025-22 cherry pick (gitea/main -> forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8197): <!--number 8197 --><!--line 0 --><!--description Rml4IHNlbnRlbmNlIHN0cnVjdHVyZSBtZW50aW9uaW5nIGNvb2xkb3duIHBlcmlvZA==-->Fix sentence structure mentioning cooldown period<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8195): <!--number 8195 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8194): <!--number 8194 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHY0MC41Ny4xIChmb3JnZWpvKQ==-->Update renovate to v40.57.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8190): <!--number 8190 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgY2hhcnQuanMgdG8gdjQuNS4wIChmb3JnZWpvKQ==-->Update dependency chart.js to v4.5.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8188): <!--number 8188 --><!--line 0 --><!--description bWFrZSB0ZXN0IHN1aXRlIHJ1biBvbiBvbGRlciBnaXQgdmVyc2lvbg==-->make test suite run on older git version<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8186): <!--number 8186 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLXNxbC1kcml2ZXIvbXlzcWwgdG8gdjEuOS4zIChmb3JnZWpvKQ==-->Update module github.com/go-sql-driver/mysql to v1.9.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8183): <!--number 8183 --><!--line 0 --><!--description VXBkYXRlIGVudmlyb25tZW50LXRvLWluaSBSRUFETUU=-->Update environment-to-ini README<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8181): <!--number 8181 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuMy41IChmb3JnZWpvKQ==-->Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.3.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8176): <!--number 8176 --><!--line 0 --><!--description RG9ja2VyZmlsZSBzaG91bGQgcmUtdXNlIGJpbmRhdGEgZmlsZXMgd2hlbiBwb3NzaWJsZQ==-->Dockerfile should re-use bindata files when possible<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8174): <!--number 8174 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgbWluaW1hdGNoIHRvIHYxMC4wLjMgKGZvcmdlam8p-->Update dependency minimatch to v10.0.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8172): <!--number 8172 --><!--line 0 --><!--description dXNlIHpzdGQuV2l0aExvd2VyRW5jb2Rlck1lbSBmb3IgZ2VuZXJhdGUtYmluZGF0YQ==-->use zstd.WithLowerEncoderMem for generate-bindata<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8168): <!--number 8168 --><!--line 0 --><!--description ZG8gbm90IG1peCB1cmZhdmUgdjIgd2l0aCB1cmZhdmUgdjM=-->do not mix urfave v2 with urfave v3<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8166): <!--number 8166 --><!--line 0 --><!--description Y2hvcmUoY2kpOiBza2lwIHRlc3RzIGlmIFRFU1Rfe01JTklPX0VORFBPSU5ULEVMQVNUSUNTRUFSQ0hfVVJMfSBpcyBub3Qgc2V0-->chore(ci): skip tests if TEST_{MINIO_ENDPOINT,ELASTICSEARCH_URL} is not set<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8163): <!--number 8163 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRsYWIuY29tL2dpdGxhYi1vcmcvYXBpL2NsaWVudC1nbyB0byB2MC4xMzAuMSAoZm9yZ2Vqbyk=-->Update module gitlab.com/gitlab-org/api/client-go to v0.130.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8162): <!--number 8162 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21pbmlvL21pbmlvLWdvL3Y3IHRvIHY3LjAuOTMgKGZvcmdlam8p-->Update module github.com/minio/minio-go/v7 to v7.0.93 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8160): <!--number 8160 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgcG9zdGNzcyB0byB2OC41LjUgKGZvcmdlam8p-->Update dependency postcss to v8.5.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8159): <!--number 8159 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgbWluaW1hdGNoIHRvIHYxMC4wLjIgKGZvcmdlam8p-->Update dependency minimatch to v10.0.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8157): <!--number 8157 --><!--line 0 --><!--description Y2hvcmUoY2kpOiB1c2UgY29kZS5mb3JnZWpvLm9yZy9mb3JnZWpvL21pZ3JhdGlvbi10ZXN0IGZvciBtaWdyYXRpb24gdGVzdHM=-->chore(ci): use code.forgejo.org/forgejo/migration-test for migration tests<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8150): <!--number 8150 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgaGFwcHktZG9tIHRvIHYxOCAoZm9yZ2Vqbyk=-->Update dependency happy-dom to v18 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8149): <!--number 8149 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgdHlwZXNjcmlwdC1lc2xpbnQgdG8gdjguMzQuMCAoZm9yZ2Vqbyk=-->Update dependency typescript-eslint to v8.34.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8148): <!--number 8148 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQHBsYXl3cmlnaHQvdGVzdCB0byB2MS41My4wIChmb3JnZWpvKQ==-->Update dependency @playwright/test to v1.53.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8147): <!--number 8147 --><!--line 0 --><!--description VXBkYXRlIGdoY3IuaW8vZGV2Y29udGFpbmVycy9mZWF0dXJlcy9naXQtbGZzIERvY2tlciB0YWcgdG8gdjEuMi40IChmb3JnZWpvKQ==-->Update ghcr.io/devcontainers/features/git-lfs Docker tag to v1.2.4 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8146): <!--number 8146 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgcG9zdGNzcy1uZXN0aW5nIHRvIHYxMy4wLjIgKGZvcmdlam8p-->Update dependency postcss-nesting to v13.0.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8145): <!--number 8145 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQHZpdGVzdC9lc2xpbnQtcGx1Z2luIHRvIHYxLjIuMiAoZm9yZ2Vqbyk=-->Update dependency @vitest/eslint-plugin to v1.2.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8144): <!--number 8144 --><!--line 0 --><!--description Y2hvcmU6IGZpeCB0ZXN0cyBmb3Igb2xkIGdpdCB2ZXJzaW9ucw==-->chore: fix tests for old git versions<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8140): <!--number 8140 --><!--line 0 --><!--description Y2hvcmUoY2kpOiBydW4gYWRkaXRpb25hbCB0ZXN0cyBpbiBpbnRlZ3JhdGlvbg==-->chore(ci): run additional tests in integration<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8137): <!--number 8137 --><!--line 0 --><!--description UmVtb3ZlIHNoZWJhbmcgZnJvbSBiYXNoIGF1dG9jb21wbGV0aW9u-->Remove shebang from bash autocompletion<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8134): <!--number 8134 --><!--line 0 --><!--description TWFrZSByZWxhdGl2ZS10aW1lIGEgc2VsZi1tYWludGFpbmluZyBjdXN0b20gZWxlbWVudA==-->Make relative-time a self-maintaining custom element<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8129): <!--number 8129 --><!--line 0 --><!--description Y3JlYXRlIHNoZWxsLm5peDsgdXBkYXRlIGZsYWtlLio=-->create shell.nix; update flake.*<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8128): <!--number 8128 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb25uZWN0cnBjLmNvbS9jb25uZWN0IHRvIHYxLjE4LjEgKGZvcmdlam8p-->Update module connectrpc.com/connect to v1.18.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8127): <!--number 8127 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgbWFya2Rvd25saW50LWNsaSB0byB2MC40NS4wIChmb3JnZWpvKQ==-->Update dependency markdownlint-cli to v0.45.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8126): <!--number 8126 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZXNsaW50LXBsdWdpbi1yZWdleHAgdG8gdjIuOS4wIChmb3JnZWpvKQ==-->Update dependency eslint-plugin-regexp to v2.9.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8125): <!--number 8125 --><!--line 0 --><!--description VXBkYXRlIHZpdGVzdCBtb25vcmVwbyB0byB2My4yLjMgKGZvcmdlam8p-->Update vitest monorepo to v3.2.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8118): <!--number 8118 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8117): <!--number 8117 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHY0MC40OC40IChmb3JnZWpvKQ==-->Update renovate to v40.48.4 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8112): <!--number 8112 --><!--line 0 --><!--description cmVtb3ZlIGRvd25sb2FkIGF0dHJpYnV0ZSBmcm9tIGV4dGVybmFsIGFzc2V0cw==-->remove download attribute from external assets<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8108): <!--number 8108 --><!--line 0 --><!--description YWx3YXlzIHJlbmRlciBkZXRhaWxlZCB0ZWFtIHBlcm1pc3Npb25zIHRhYmxlIGluIHNpZGViYXI=-->always render detailed team permissions table in sidebar<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8103): <!--number 8103 --><!--line 0 --><!--description VXBkYXRlIHgvdG9vbHMgdG8gdjAuMzQuMCAoZm9yZ2Vqbyk=-->Update x/tools to v0.34.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8102): <!--number 8102 --><!--line 0 --><!--description VXBkYXRlIHZpdGVzdCBtb25vcmVwbyB0byB2My4yLjIgKGZvcmdlam8p-->Update vitest monorepo to v3.2.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8101): <!--number 8101 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2VkaXRvcmNvbmZpZy1jaGVja2VyL2VkaXRvcmNvbmZpZy1jaGVja2VyL3YzL2NtZC9lZGl0b3Jjb25maWctY2hlY2tlciB0byB2My4zLjAgKGZvcmdlam8p-->Update module github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker to v3.3.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8099): <!--number 8099 --><!--line 0 --><!--description VXBkYXRlIGxpbnRlcnMgKGZvcmdlam8p-->Update linters (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8098): <!--number 8098 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgaGFwcHktZG9tIHRvIHYxNy42LjMgKGZvcmdlam8p-->Update dependency happy-dom to v17.6.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8097): <!--number 8097 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQHZpdGVqcy9wbHVnaW4tdnVlIHRvIHY1LjIuNCAoZm9yZ2Vqbyk=-->Update dependency @vitejs/plugin-vue to v5.2.4 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8096): <!--number 8096 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQGF4ZS1jb3JlL3BsYXl3cmlnaHQgdG8gdjQuMTAuMiAoZm9yZ2Vqbyk=-->Update dependency @axe-core/playwright to v4.10.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8094): <!--number 8094 --><!--line 0 --><!--description c2hvdyBtZW1iZXJzaGlwIG9mIGxpbWl0ZWQgb3Jncw==-->show membership of limited orgs<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8091): <!--number 8091 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvY3J5cHRvIHRvIHYwLjM5LjAgKGZvcmdlam8p-->Update module golang.org/x/crypto to v0.39.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8090): <!--number 8090 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3NlcmdpL2dvLWRpZmYgdG8gdjEuNC4wIChmb3JnZWpvKQ==-->Update module github.com/sergi/go-diff to v1.4.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8086): <!--number 8086 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuNCAoZm9yZ2Vqbyk=-->Update dependency go to v1.24.4 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8078): <!--number 8078 --><!--line 0 --><!--description RmVkZXJhdGVkIHVzZXIgYWN0aXZpdHkgZm9sbG93aW5nOiBJc29sYXRlZCBtb2RlbCBjaGFuZ2Vz-->Federated user activity following: Isolated model changes<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8066): <!--number 8066 --><!--line 0 --><!--description cmVuYW1lIGFwaS57TGlzdCx9QWN0aW9uUnVuIHRvIGFwaS57TGlzdCx9UmVwb0FjdGlvblJ1bg==-->rename api.{List,}ActionRun to api.{List,}RepoActionRun<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8065): <!--number 8065 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby51YmVyLm9yZy9tb2NrL21vY2tnZW4gdG8gdjAuNS4yIChmb3JnZWpvKQ==-->Update module go.uber.org/mock/mockgen to v0.5.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8064): <!--number 8064 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2JsZXZlc2VhcmNoL2JsZXZlL3YyIHRvIHYyLjUuMiAoZm9yZ2Vqbyk=-->Update module github.com/blevesearch/bleve/v2 to v2.5.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8063): <!--number 8063 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgdnVlIHRvIHYzLjUuMTYgKGZvcmdlam8p-->Update dependency vue to v3.5.16 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8062): <!--number 8062 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgcG9zdGNzcyB0byB2OC41LjQgKGZvcmdlam8p-->Update dependency postcss to v8.5.4 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8061): <!--number 8061 --><!--line 0 --><!--description Y2hvcmU6IGV4dHJhY3QgY29tbWl0IGhlYWRlciB0ZW1wbGF0ZQ==-->chore: extract commit header template<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8058): <!--number 8058 --><!--line 0 --><!--description Y2hvcmU6IGRyb3AgdW51c2VkIGBtaXNzcGVsbGA=-->chore: drop unused `misspell`<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8056): <!--number 8056 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb2RlLmZvcmdlam8ub3JnL2YzL2dvZjMvdjMgdG8gdjMuMTEuMCAoZm9yZ2Vqbyk=-->Update module code.forgejo.org/f3/gof3/v3 to v3.11.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8055): <!--number 8055 --><!--line 0 --><!--description Y2hvcmUocmVub3ZhdGUpOiBkaXNhYmxlIGluZGlyZWN0IGRpZ2VzdCB1cGRhdGVzIGZvciBzdGFibGU=-->chore(renovate): disable indirect digest updates for stable<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8054): <!--number 8054 --><!--line 0 --><!--description Y2hvcmU6IGRyb3AgdW51c2VkIGBAdHlwZXNjcmlwdC1lc2xpbnQvcGFyc2VyYCBwYWNrYWdl-->chore: drop unused `@typescript-eslint/parser` package<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8052): <!--number 8052 --><!--line 0 --><!--description VXBkYXRlIGxpbnRlcnMgKGZvcmdlam8p-->Update linters (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8051): <!--number 8051 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgaGFwcHktZG9tIHRvIHYxNy42LjEgKGZvcmdlam8p-->Update dependency happy-dom to v17.6.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8050): <!--number 8050 --><!--line 0 --><!--description Y2hvcmUocmVub3ZhdGUpOiBidW1wIHRvIHY0MC40MC4wIGFuZCBkaXNhYmxlIHY3-->chore(renovate): bump to v40.40.0 and disable v7<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8049): <!--number 8049 --><!--line 0 --><!--description Q0xJIGlzIGZvcmdlam8gbm90IEZvcmdlam8=-->CLI is forgejo not Forgejo<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8044): <!--number 8044 --><!--line 0 --><!--description YWRkIG1pc3NpbmcgYm90dG9tIG1hcmdpbiBmb3IgdmVyaWZpY2F0aW9uLWJ1dHRvbiBpbiByZWxlYXNlIHZpZXc=-->add missing bottom margin for verification-button in release view<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8041): <!--number 8041 --><!--line 0 --><!--description W2dpdGVhXSBBbHdheXMgdXNlIGFuIGVtcHR5IGxpbmUgdG8gc2VwYXJhdGUgdGhlIGNvbW1pdCBtZXNzYWdlIGFuZCB0cmFpbGVy-->[gitea] Always use an empty line to separate the commit message and trailer<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8040): <!--number 8040 --><!--line 0 --><!--description W2dpdGVhXSB3ZWVrIDIwMjUtMjEgY2hlcnJ5IHBpY2sgKGdpdGVhL21haW4gLT4gZm9yZ2Vqbyk=-->[gitea] week 2025-21 cherry pick (gitea/main -> forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8038): <!--number 8038 --><!--line 0 --><!--description QWRkIGEgR05VIEd1aXggbWFuaWZlc3Q=-->Add a GNU Guix manifest<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8021): <!--number 8021 --><!--line 0 --><!--description Y2hvcmUoY2xlYW51cCk6IHN1cHByZXNzIG5vbiBhY3Rpb25hYmxlIFhPUk0gd2FybmluZ3M=-->chore(cleanup): suppress non actionable XORM warnings<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8019): <!--number 8019 --><!--line 0 --><!--description bWlncmF0ZSByZXBvc2l0b3J5LnRvcGljcyBjb2x1bW4gZm9yIFNRTGl0ZQ==-->migrate repository.topics column for SQLite<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7994): <!--number 7994 --><!--line 0 --><!--description Y2hvcmUoY2xlYW51cCk6IHJlcGxhY2VzIHVubmVjZXNzYXJ5IGNhbGxzIHRvIGZvcm1hdHRpbmcgZnVuY3Rpb25zIGJ5IG5vbi1mb3JtYXR0aW5nIGVxdWl2YWxlbnRz-->chore(cleanup): replaces unnecessary calls to formatting functions by non-formatting equivalents<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7987): <!--number 7987 --><!--line 0 --><!--description YWdncmVnYXRlIGRlbGV0ZWQgdGVhbSBhcyBnaG9zdCB0ZWFt-->aggregate deleted team as ghost team<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7981): <!--number 7981 --><!--line 0 --><!--description YWRkIHZhbGlkYXRpbmcgdXNlciBwYXNzd29yZCBhcyB0cmFjZSByZWdpb24=-->add validating user password as trace region<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7978): <!--number 7978 --><!--line 0 --><!--description Y2hvcmUoY2xlYW51cCk6IGZpeCBhbmQgc2ltcGxpZnkgQVBJIGNvbXBhcmlzb24gaGVscGVy-->chore(cleanup): fix and simplify API comparison helper<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7975): <!--number 7975 --><!--line 0 --><!--description Zml4KGkxOG4pOiB1c2UgY29ycmVjdCBiYXNlIGNhcGl0YWxpemF0aW9uIHN0eWxl-->fix(i18n): use correct base capitalization style<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7961): <!--number 7961 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7959): <!--number 7959 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHY0MC4zMS4wIChmb3JnZWpvKQ==-->Update renovate to v40.31.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7954): <!--number 7954 --><!--line 0 --><!--description VXBkYXRlIGZvcmdlam8gZ28tY2hpIHBhY2thZ2VzIChmb3JnZWpvKQ==-->Update forgejo go-chi packages (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7952): <!--number 7952 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL1Byb3Rvbk1haWwvZ28tY3J5cHRvIHRvIHYxLjMuMCAoZm9yZ2Vqbyk=-->Update module github.com/ProtonMail/go-crypto to v1.3.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7950): <!--number 7950 --><!--line 0 --><!--description Zml4KHVpKTogcmVsYXRpdmUgdGltZSBlbGVtZW50cyB3ZXJlIHJlc2V0IG9uIGh0bXggc3dhcA==-->fix(ui): relative time elements were reset on htmx swap<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7945): <!--number 7945 --><!--line 0 --><!--description YG92ZXJmbG93LXdyYXBgIHN0cmF0ZWd5IGluIGAubWFya3VwYCBDU1MgY2xhc3M=-->`overflow-wrap` strategy in `.markup` CSS class<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7944): <!--number 7944 --><!--line 0 --><!--description Zml4KHVpKTogY2hhbmdlIGVzY2FwaW5nIGJ1dHRvbiBiZyBvbiBzZWxlY3RlZCBsaW5lcw==-->fix(ui): change escaping button bg on selected lines<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7933): <!--number 7933 --><!--line 0 --><!--description ZG8gbm90IHVuY29uZGl0aW9uYWxseSBhcHBlbmQgJChHSVRFQV9DT01QQVRJQklMSVRZKSBpbiB2ZXJzaW9u-->do not unconditionally append $(GITEA_COMPATIBILITY) in version<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7925): <!--number 7925 --><!--line 0 --><!--description Zml4KHVpKTogY2VudGVyIGZvb3RlciBsaW5rcw==-->fix(ui): center footer links<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7922): <!--number 7922 --><!--line 0 --><!--description VXBkYXRlIGdvLW9wZW5hcGkgcGFja2FnZXMgKGZvcmdlam8p-->Update go-openapi packages (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7920): <!--number 7920 --><!--line 0 --><!--description dW5pZnkgcmVwb3NpdG9yeSB0b3BpY3MgZmllbGQgYnkgcmVwbGFjaW5nIEpTT04gbnVsbCB3aXRoIGVtcHR5IGFycmF5-->unify repository topics field by replacing JSON null with empty array<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7919): <!--number 7919 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgd2VicGFjayB0byB2NS45OS45IChmb3JnZWpvKQ==-->Update dependency webpack to v5.99.9 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7918): <!--number 7918 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgc2hhcnAgdG8gdjAuMzQuMiAoZm9yZ2Vqbyk=-->Update dependency sharp to v0.34.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7917): <!--number 7917 --><!--line 0 --><!--description Y2hvcmU6IFFvTCBpbXByb3ZlbWVudHMgdG8gdGVzdHM=-->chore: QoL improvements to tests<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7914): <!--number 7914 --><!--line 0 --><!--description Y2hvcmUocmVub3ZhdGUpOiBkaXNhYmxlIGluZGlyZWN0IG1ham9yIHVwZGF0ZXMgZm9yIHN0YWJsZSBicmFuY2hlcw==-->chore(renovate): disable indirect major updates for stable branches<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7910): <!--number 7910 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgY2xpcHBpZSB0byB2NC4xLjcgKGZvcmdlam8p-->Update dependency clippie to v4.1.7 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7908): <!--number 7908 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7907): <!--number 7907 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHY0MC4yNi4wIChmb3JnZWpvKQ==-->Update renovate to v40.26.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7901): <!--number 7901 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3l1aW4vZ29sZG1hcmsgdG8gdjEuNy4xMiAoZm9yZ2Vqbyk=-->Update module github.com/yuin/goldmark to v1.7.12 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7898): <!--number 7898 --><!--line 0 --><!--description Y2hvcmUodWkpOiBjbGVhbnVwIHVudXNlZCBjb2xvciBDU1M=-->chore(ui): cleanup unused color CSS<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7894): <!--number 7894 --><!--line 0 --><!--description Zml4KHVpKTogZml4IGZvcmNlLXB1c2ggY29tcGFyZSBsaW5lIGxheW91dA==-->fix(ui): fix force-push compare line layout<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7890): <!--number 7890 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2FsZWN0aG9tYXMvY2hyb21hL3YyIHRvIHYyLjE4LjAgKGZvcmdlam8p-->Update module github.com/alecthomas/chroma/v2 to v2.18.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7884): <!--number 7884 --><!--line 0 --><!--description cGFyc2UgYGNoYW5nZS1pZGAgaW4gdGhlIGdpdCBjb21taXQgaGVhZGVy-->parse `change-id` in the git commit header<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7881): <!--number 7881 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2JsZXZlc2VhcmNoL2JsZXZlL3YyIHRvIHYyLjUuMSAoZm9yZ2Vqbyk=-->Update module github.com/blevesearch/bleve/v2 to v2.5.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7879): <!--number 7879 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgdnVlIHRvIHYzLjUuMTQgKGZvcmdlam8p-->Update dependency vue to v3.5.14 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7877): <!--number 7877 --><!--line 0 --><!--description TWlncmF0ZSByZW5vdmF0ZSBjb25maWc=-->Migrate renovate config<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7872): <!--number 7872 --><!--line 0 --><!--description Zml4KHVpKTogZGlzYWJsZSBhdXRvY2FwaXRhbGl6YXRpb24vYXV0b2NvcnJlY3QgZm9yIHVzZXJuYW1lIGlucHV0cw==-->fix(ui): disable autocapitalization/autocorrect for username inputs<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7868): <!--number 7868 --><!--line 0 --><!--description Zml4KHVpKTogZGlzYWJsZSBzcGVsbGNoZWNrIG9uIFRPVFAgZm9ybSBmaWVsZHM=-->fix(ui): disable spellcheck on TOTP form fields<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7866): <!--number 7866 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSB1bnVzZWQgdXBkYXRlLWxvY2FsZXMuc2g=-->chore: remove unused update-locales.sh<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7857): <!--number 7857 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21zdGVpbmVydC9wYW0vdjIgdG8gdjIuMS4wIChmb3JnZWpvKQ==-->Update module github.com/msteinert/pam/v2 to v2.1.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7856): <!--number 7856 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb2RlLmZvcmdlam8ub3JnL2Zvcmdlam8vYWN0IHRvIHYxLjI2LjAgKGZvcmdlam8p-->Update module code.forgejo.org/forgejo/act to v1.26.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7852): <!--number 7852 --><!--line 0 --><!--description Rml4IFRlc3RTU0hQdXNoTWlycm9yL05vcm1hbC9DaGVja19taXJyb3JlZF9jb250ZW50IHRlc3Q=-->Fix TestSSHPushMirror/Normal/Check_mirrored_content test<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7849): <!--number 7849 --><!--line 0 --><!--description VXBkYXRlIGdpdGh1Yi5jb20vZ29sYW5nLWp3dC9qd3QvdjQgKGluZGlyZWN0KSB0byB2NC41LjIgW1NFQ1VSSVRZXSAoZm9yZ2Vqbyk=-->Update github.com/golang-jwt/jwt/v4 (indirect) to v4.5.2 [SECURITY] (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7848): <!--number 7848 --><!--line 0 --><!--description Y2kocmVub3ZhdGUpOiBvbmx5IGZhaWwgb24gZXJyb3I=-->ci(renovate): only fail on error<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7847): <!--number 7847 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL25pa2xhc2Zhc2NoaW5nL2dvLW9yZyB0byB2MS44LjAgKGZvcmdlam8p-->Update module github.com/niklasfasching/go-org to v1.8.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7840): <!--number 7840 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7835): <!--number 7835 --><!--line 0 --><!--description cmVtb3ZlIHJlZHVuZGFudCBwZXJtaXNzaW9uIGNoZWNrIGluIFJlbW92ZUxhYmVs-->remove redundant permission check in RemoveLabel<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7833): <!--number 7833 --><!--line 0 --><!--description dGVzdCh1aS1lMmUpOiBmaXggZmxha3kgcmVwbyB3aWtpIHRlc3Q=-->test(ui-e2e): fix flaky repo wiki test<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7830): <!--number 7830 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLXdlYmF1dGhuL3dlYmF1dGhuIHRvIHYwLjEzLjAgKGZvcmdlam8p-->Update module github.com/go-webauthn/webauthn to v0.13.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7822): <!--number 7822 --><!--line 0 --><!--description Y2hvcmUodWkpOiBjbGVhbiB1cCBoYXNoYm94IENTUywgc21hbGwgZGVzaWduIGNoYW5nZXM=-->chore(ui): clean up hashbox CSS, small design changes<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7817): <!--number 7817 --><!--line 0 --><!--description cmVwbGFjZSDDnyB3aXRoIHNzIGluIG5vcm1hbGl6ZVVzZXJOYW1l-->replace ß with ss in normalizeUserName<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7814): <!--number 7814 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ2xvYmFscyB0byB2MTYuMS4wIChmb3JnZWpvKQ==-->Update dependency globals to v16.1.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7809): <!--number 7809 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvb2F1dGgyIHRvIHYwLjMwLjAgKGZvcmdlam8p-->Update module golang.org/x/oauth2 to v0.30.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7807): <!--number 7807 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuMyAoZm9yZ2Vqbyk=-->Update dependency go to v1.24.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7799): <!--number 7799 --><!--line 0 --><!--description YWRkIG1pc3NpbmcgbG9hZGJhbGFuY2luZyBwb2xpY2llcyBmb3IgRW5naW5lR3JvdXAgY29ubmVjdGlvbnM=-->add missing loadbalancing policies for EngineGroup connections<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7798): <!--number 7798 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvbmV0IHRvIHYwLjQwLjAgKGZvcmdlam8p-->Update module golang.org/x/net to v0.40.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7797): <!--number 7797 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvaW1hZ2UgdG8gdjAuMjcuMCAoZm9yZ2Vqbyk=-->Update module golang.org/x/image to v0.27.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7792): <!--number 7792 --><!--line 0 --><!--description W3NraXAgY2ldIGNob3JlOiByZW1vdmUgYmFja3BvcnQgc2NyaXB0-->[skip ci] chore: remove backport script<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7789): <!--number 7789 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMS42IChmb3JnZWpvKQ==-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.6 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7785): <!--number 7785 --><!--line 0 --><!--description W1NLSVAgQ0ldIGNob3JlOiB1cGRhdGUgQ09ERU9XTkVSUw==-->[SKIP CI] chore: update CODEOWNERS<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7784): <!--number 7784 --><!--line 0 --><!--description Zml4KGFwaSk6IGRvY3VtZW50IGBpc19zeXN0ZW1fd2ViaG9va2AgZmllbGQ=-->fix(api): document `is_system_webhook` field<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7778): <!--number 7778 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7777): <!--number 7777 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHY0MCAoZm9yZ2VqbykgKG1ham9yKQ==-->Update renovate to v40 (forgejo) (major)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7776): <!--number 7776 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHYzOS4yNjQuMCAoZm9yZ2Vqbyk=-->Update renovate to v39.264.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7773): <!--number 7773 --><!--line 0 --><!--description cmVtb3ZlIGFydGlmaWNpYWwgZGVsYXkgZm9yIFBSIHVwZGF0ZQ==-->remove artificial delay for PR update<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7772): <!--number 7772 --><!--line 0 --><!--description Y2hvcmU6IEZpeCBvdXRkYXRlZCB1c2FnZSBvZiB1bml0dGVzdC5PdmVycmlkZUZpeHR1cmVz-->chore: Fix outdated usage of unittest.OverrideFixtures<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7770): <!--number 7770 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tLzQyd2ltL2h0dHBzaWcgdG8gdjEuMi4zIChmb3JnZWpvKQ==-->Update module github.com/42wim/httpsig to v1.2.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7769): <!--number 7769 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQGdpdGh1Yi9yZWxhdGl2ZS10aW1lLWVsZW1lbnQgdG8gdjQuNC42IChmb3JnZWpvKQ==-->Update dependency @github/relative-time-element to v4.4.6 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7768): <!--number 7768 --><!--line 0 --><!--description VXBkYXRlIGdpdGh1Yi5jb20vNDJ3aW0vc3Noc2lnIGRpZ2VzdCB0byA1MTAwNjMyIChmb3JnZWpvKQ==-->Update github.com/42wim/sshsig digest to 5100632 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7765): <!--number 7765 --><!--line 0 --><!--description Y2hvcmUocmVsZWFzZS1ub3Rlcyk6IEZvcmdlam8gdjcuMC4xNQ==-->chore(release-notes): Forgejo v7.0.15<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7764): <!--number 7764 --><!--line 0 --><!--description Y2hvcmUocmVsZWFzZS1ub3Rlcyk6IEZvcmdlam8gdjExLjAuMQ==-->chore(release-notes): Forgejo v11.0.1<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7762): <!--number 7762 --><!--line 0 --><!--description ZG9jdW1lbnQgdGhhdCAvcmVwb3Mve293bmVyfS97cmVwb30vcHVsbHMgbWF5IGNvbnRhaW4gbnVsbHM=-->document that /repos/{owner}/{repo}/pulls may contain nulls<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7760): <!--number 7760 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZm9yZ2Vqby9yZWxlYXNlLW5vdGVzLWFzc2lzdGFudCB0byB2MS4yLjUgKGZvcmdlam8p-->Update dependency forgejo/release-notes-assistant to v1.2.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7759): <!--number 7759 --><!--line 0 --><!--description Y2hvcmUocmVub3ZhdGUpOiB1c2UgYGdpdGVhLXJlbGVhc2VzYCBkYXRhc291cmNlIGZvciBybmE=-->chore(renovate): use `gitea-releases` datasource for rna<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7758): <!--number 7758 --><!--line 0 --><!--description Y2hvcmUocmVub3ZhdGUpOiBhbGxvdyB1cGRhdGluZyByZWxlYXNlIG5vdGVzIGFzc2lzdGFudA==-->chore(renovate): allow updating release notes assistant<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7746): <!--number 7746 --><!--line 0 --><!--description Zml4KHVpKTogaW1wcm92ZSBmb3JjZS1wdXNoIGNvbXBhcmUgbGluZSBsYXlvdXQ=-->fix(ui): improve force-push compare line layout<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7744): <!--number 7744 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZXNsaW50LXBsdWdpbi11bmljb3JuIHRvIHY1OSAoZm9yZ2Vqbyk=-->Update dependency eslint-plugin-unicorn to v59 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7740): <!--number 7740 --><!--line 0 --><!--description Zml4KHVpKTogbXVsdGlwbGUgZml4ZXMgb2Ygc3luYyBmb3JrIFVJ-->fix(ui): multiple fixes of sync fork UI<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7739): <!--number 7739 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3JlZGlzL2dvLXJlZGlzL3Y5IHRvIHY5LjguMCAoZm9yZ2Vqbyk=-->Update module github.com/redis/go-redis/v9 to v9.8.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7738): <!--number 7738 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2FsZWN0aG9tYXMvY2hyb21hL3YyIHRvIHYyLjE3LjIgKGZvcmdlam8p-->Update module github.com/alecthomas/chroma/v2 to v2.17.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7736): <!--number 7736 --><!--line 0 --><!--description VXBkYXRlIGxpbnRlcnMgKGZvcmdlam8p-->Update linters (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7735): <!--number 7735 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgaGFwcHktZG9tIHRvIHYxNy40LjYgKGZvcmdlam8p-->Update dependency happy-dom to v17.4.6 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7732): <!--number 7732 --><!--line 0 --><!--description Y2k6IGFkZCBjbGFyaWZpY2F0aW9uIHJlZ2FyZGluZyB0ZXN0IGxhYmVs-->ci: add clarification regarding test label<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7731): <!--number 7731 --><!--line 0 --><!--description Y2hvcmU6IGZpeCB0ZXN0IHRvIGF2b2lkIGRhdGEgcmFjZQ==-->chore: fix test to avoid data race<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7728): <!--number 7728 --><!--line 0 --><!--description cmVmYWN0b3IgJiBlbmhhbmNlIEFQIGVsZW1lbnRzIHVzZWQ=-->refactor & enhance AP elements used<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7720): <!--number 7720 --><!--line 0 --><!--description Y2hvcmUocmVsZWFzZSk6IG5leHQtZGlnZXN0IG1vdmVkIHRvIGludmlzaWJsZS5mb3JnZWpvLm9yZw==-->chore(release): next-digest moved to invisible.forgejo.org<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7715): <!--number 7715 --><!--line 0 --><!--description Y2hvcmU6IHJlcGxhY2UgYGdpdGh1Yi5jb20vZ28tdGVzdGZpeHR1cmVzL3Rlc3RmaXh0dXJlc2A=-->chore: replace `github.com/go-testfixtures/testfixtures`<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7714): <!--number 7714 --><!--line 0 --><!--description ZW5oYW5jZSB2YWxpZGF0ZWFibGUgaW50ZXJmYWNl-->enhance validateable interface<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7713): <!--number 7713 --><!--line 0 --><!--description W2dpdGVhXSB3ZWVrIDIwMjUtMTcgY2hlcnJ5IHBpY2sgKGdpdGVhL21haW4gLT4gZm9yZ2Vqbyk=-->[gitea] week 2025-17 cherry pick (gitea/main -> forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7707): <!--number 7707 --><!--line 0 --><!--description ZG8gbm90IHNldCBHT1BST1hZPWRpcmVjdCBpbiBEb2NrZXJmaWxlKg==-->do not set GOPROXY=direct in Dockerfile*<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7705): <!--number 7705 --><!--line 0 --><!--description Y2hvcmUodWkpOiByZW1vdmUgdW51c2VkIGZvbWFudGljIGZvbnQgc2l6ZSBjbGFzc2Vz-->chore(ui): remove unused fomantic font size classes<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7697): <!--number 7697 --><!--line 0 --><!--description YmV0dGVyIGNvbW1lbnRzIGFuZCB2YXJpYWJsZSBuYW1lcyBmb3IgQWN0aW9uUnVuTm93RG9uZQ==-->better comments and variable names for ActionRunNowDone<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7696): <!--number 7696 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7695): <!--number 7695 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHYzOS4yNjEuNCAoZm9yZ2Vqbyk=-->Update renovate to v39.261.4 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7690): <!--number 7690 --><!--line 0 --><!--description Zml4IHZhcmlvdXMgdHlwb3M=-->fix various typos<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7689): <!--number 7689 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3l1aW4vZ29sZG1hcmsgdG8gdjEuNy4xMSAoZm9yZ2Vqbyk=-->Update module github.com/yuin/goldmark to v1.7.11 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7687): <!--number 7687 --><!--line 0 --><!--description Y2hvcmU6IHR1bmUgZG93biByZW1vdGUgdXNlciBwcm9tb3Rpb24gZGVidWcgbWVzc2FnZSBzaG93biBhcyBlcnJvcg==-->chore: tune down remote user promotion debug message shown as error<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7685): <!--number 7685 --><!--line 0 --><!--description dXNlIGBsaW5ndWlzdC1nZW5lcmF0ZWRgIGZvciBsYW5ndWFnZSBzdGF0cw==-->use `linguist-generated` for language stats<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7683): <!--number 7683 --><!--line 0 --><!--description c2V0IGRlZmF1bHQgcmVzdHJpY3RlZCBmb3IgT0F1dGgyIHVzZXI=-->set default restricted for OAuth2 user<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7682): <!--number 7682 --><!--line 0 --><!--description Y2hvcmU6IHNpbXBsaWZ5IGBHZXREaWZmYA==-->chore: simplify `GetDiff`<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7680): <!--number 7680 --><!--line 0 --><!--description Y2hvcmU6IHJlbW92ZSB1bnVzZWQgbGludGVycw==-->chore: remove unused linters<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7678): <!--number 7678 --><!--line 0 --><!--description YWRkIGxhYmVsIGZvciBhdmF0YXIgc2V0dGluZ3M=-->add label for avatar settings<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7667): <!--number 7667 --><!--line 0 --><!--description aTE4bihlbik6IGZpeCB0eXBvIGluIGFyY2hpdmUgbm90aWNl-->i18n(en): fix typo in archive notice<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7665): <!--number 7665 --><!--line 0 --><!--description VXBkYXRlIGxpbnRlcnMgKGZvcmdlam8p-->Update linters (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7663): <!--number 7663 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQHBsYXl3cmlnaHQvdGVzdCB0byB2MS41Mi4wIChmb3JnZWpvKQ==-->Update dependency @playwright/test to v1.52.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7662): <!--number 7662 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL1B1ZXJraXRvQmlvL2dvcXVlcnkgdG8gdjEuMTAuMyAoZm9yZ2Vqbyk=-->Update module github.com/PuerkitoBio/goquery to v1.10.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7661): <!--number 7661 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMS41IChmb3JnZWpvKQ==-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7659): <!--number 7659 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgd2VicGFjayB0byB2NS45OS43IChmb3JnZWpvKQ==-->Update dependency webpack to v5.99.7 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7648): <!--number 7648 --><!--line 0 --><!--description Y2hvcmU6IG1lcmdlIHRlc3RzLkFkZEZpeHR1cmVzIGFuZCB1bml0dGVzdC5PdmVycmlkZUZpeHR1cmVz-->chore: merge tests.AddFixtures and unittest.OverrideFixtures<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7640): <!--number 7640 --><!--line 0 --><!--description UmVtb3ZlICJjcmVhdGUgYnJhbmNoIiBidXR0b24gb24gbWlycm9yZWQgcmVwb3M=-->Remove "create branch" button on mirrored repos<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7616): <!--number 7616 --><!--line 0 --><!--description Zml4KHVpKTogbWFrZSBwYWdpbmF0aW9uIGxhYmVscyBhbHdheXMgdmlzaWJsZSB0byBzY3JlZW5yZWFkZXI=-->fix(ui): make pagination labels always visible to screenreader<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7613): <!--number 7613 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBtdmRhbi5jYy9nb2Z1bXB0IHRvIHYwLjguMCAoZm9yZ2Vqbyk=-->Update module mvdan.cc/gofumpt to v0.8.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7612): <!--number 7612 --><!--line 0 --><!--description VXBkYXRlIGxpbnRlcnMgKGZvcmdlam8p-->Update linters (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7611): <!--number 7611 --><!--line 0 --><!--description VXBkYXRlIHZpdGVzdCBtb25vcmVwbyB0byB2My4xLjIgKGZvcmdlam8p-->Update vitest monorepo to v3.1.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7610): <!--number 7610 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQHZpdGVzdC9lc2xpbnQtcGx1Z2luIHRvIHYxLjEuNDMgKGZvcmdlam8p-->Update dependency @vitest/eslint-plugin to v1.1.43 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7607): <!--number 7607 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2FsZWN0aG9tYXMvY2hyb21hL3YyIHRvIHYyLjE3LjAgKGZvcmdlam8p-->Update module github.com/alecthomas/chroma/v2 to v2.17.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7606): <!--number 7606 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21pbmlvL21pbmlvLWdvL3Y3IHRvIHY3LjAuOTEgKGZvcmdlam8p-->Update module github.com/minio/minio-go/v7 to v7.0.91 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7602): <!--number 7602 --><!--line 0 --><!--description W2dpdGVhXSB3ZWVrIDIwMjUtMTYgY2hlcnJ5IHBpY2sgKGdpdGVhL21haW4gLT4gZm9yZ2Vqbyk=-->[gitea] week 2025-16 cherry pick (gitea/main -> forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7597): <!--number 7597 --><!--line 0 --><!--description ZGVsYXktd3JpdGUgdHJhY2UuZGF0IGZvciBmb3JnZWpvIGRpYWdub3Npcw==-->delay-write trace.dat for forgejo diagnosis<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7588): <!--number 7588 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7587): <!--number 7587 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHYzOS4yNTIuMCAoZm9yZ2Vqbyk=-->Update renovate to v39.252.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7580): <!--number 7580 --><!--line 0 --><!--description ZmVhdCh1aSk6IGVubGFyZ2UgbWV0YWRhdGEgbGluZSBnYXBzIGluIGlzc3VlIGxpc3QgYW5kIHJlZmFjdG9y-->feat(ui): enlarge metadata line gaps in issue list and refactor<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7579): <!--number 7579 --><!--line 0 --><!--description aTE4bihlbik6IGFkZCBwb3NpdGlvbmFsIGhpbnRzIHRvIHN5bmNfZm9yayBwbGFjZWhvbGRlcnM=-->i18n(en): add positional hints to sync_fork placeholders<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7578): <!--number 7578 --><!--line 0 --><!--description Zml4KHVpKTogb3ZlcmZsb3cgdGFidWxhciBtZW51IENTUyBmaXhlcw==-->fix(ui): overflow tabular menu CSS fixes<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7577): <!--number 7577 --><!--line 0 --><!--description ZmVhdCh1aSk6IG1ha2UgZm9yayByZWxhdGVkIGJhbm5lcnMgbW9yZSBjb25zaXN0ZW50-->feat(ui): make fork related banners more consistent<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7575): <!--number 7575 --><!--line 0 --><!--description Zml4KHVpKTogdXNlIGNvcnJlY3QgYnJhbmNoIG5hbWUgaW4gYnJhbmNoIHRhZyBzZWxlY3Rvcg==-->fix(ui): use correct branch name in branch tag selector<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7573): <!--number 7573 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgd2VicGFjayB0byB2NS45OS42IChmb3JnZWpvKQ==-->Update dependency webpack to v5.99.6 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7571): <!--number 7571 --><!--line 0 --><!--description Zml4KHVpKTogc2hvdyBjb21taXQgaWNvbiBpbiBicmFuY2ggZHJvcGRvd24gYnV0dG9uIHdoZW4gdmlld2luZyBhIGNvbW1pdA==-->fix(ui): show commit icon in branch dropdown button when viewing a commit<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7565): <!--number 7565 --><!--line 0 --><!--description Z3JhbW1hciBpbiBhIHJlbGVhc2UgQVBJIGVycm9yIG1lc3NhZ2U=-->grammar in a release API error message<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7561): <!--number 7561 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2NhZGR5c2VydmVyL2NlcnRtYWdpYyB0byB2MC4yMy4wIChmb3JnZWpvKQ==-->Update module github.com/caddyserver/certmagic to v0.23.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7560): <!--number 7560 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21hdHRuL2dvLXNxbGl0ZTMgdG8gdjEuMTQuMjggKGZvcmdlam8p-->Update module github.com/mattn/go-sqlite3 to v1.14.28 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7558): <!--number 7558 --><!--line 0 --><!--description Zml4KHVpKTogbWFrZSB0YWcgZHJvcGRvd24gY2xpY2thYmxlIGFnYWlu-->fix(ui): make tag dropdown clickable again<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7557): <!--number 7557 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgcHl0aG9uIHRvIHYzLjEzLjMgKGZvcmdlam8p-->Update dependency python to v3.13.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7555): <!--number 7555 --><!--line 0 --><!--description Y2hvcmUocmVsZWFzZSk6IHYxMC4wIGlzIEVPTCBbc2tpcCBjaV0=-->chore(release): v10.0 is EOL [skip ci]<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7554): <!--number 7554 --><!--line 0 --><!--description Y2hvcmUocmVub3ZhdGUpOiBmaXggcGFja2FnZSBuYW1lIG1hdGNoaW5nIGZvciBnbyBtYWpvcnMgW3NraXAgY2ld-->chore(renovate): fix package name matching for go majors [skip ci]<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7552): <!--number 7552 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMS4yIChmb3JnZWpvKQ==-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7551): <!--number 7551 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9hY3Rpb25zL2dpdC1iYWNrcG9ydGluZyBhY3Rpb24gdG8gdjQuOC41IChmb3JnZWpvKQ==-->Update https://data.forgejo.org/actions/git-backporting action to v4.8.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7550): <!--number 7550 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgY2hhcnQuanMgdG8gdjQuNC45IChmb3JnZWpvKQ==-->Update dependency chart.js to v4.4.9 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7545): <!--number 7545 --><!--line 0 --><!--description VXBkYXRlIE5vZGUuanMgdG8gdjIyIChmb3JnZWpvKQ==-->Update Node.js to v22 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7543): <!--number 7543 --><!--line 0 --><!--description bWF0Y2ggUGFja2FnZUJsb2IuSGFzaEJsYWtlMmIgZGVmaW5pdGlvbiBhbmQgbWlncmF0aW9u-->match PackageBlob.HashBlake2b definition and migration<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7539): <!--number 7539 --><!--line 0 --><!--description Zml4KFVJKTogaTE4bjogaW1wcm92ZSBuYW1pbmc=-->fix(UI): i18n: improve naming<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7538): <!--number 7538 --><!--line 0 --><!--description W2dpdGVhXSB3ZWVrIDIwMjUtMTUgY2hlcnJ5IHBpY2sgKGdpdGVhL21haW4gLT4gZm9yZ2Vqbyk=-->[gitea] week 2025-15 cherry pick (gitea/main -> forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7534): <!--number 7534 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7532): <!--number 7532 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHYzOS4yNDAuMSAoZm9yZ2Vqbyk=-->Update renovate to v39.240.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7528): <!--number 7528 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvdjIvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIuMS4xIChmb3JnZWpvKQ==-->Update module github.com/golangci/golangci-lint/v2/cmd/golangci-lint to v2.1.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7520): <!--number 7520 --><!--line 0 --><!--description cGFja2FnZV9ibG9iLmhhc19ibGFrZTJiIG1heSBiZSBudWxs-->package_blob.has_blake2b may be null<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7512): <!--number 7512 --><!--line 0 --><!--description Y2hvcmU6IHVzZSBgc2hhcnBgIHRvIGdlbmVyYXRlIGltYWdlcw==-->chore: use `sharp` to generate images<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7510): <!--number 7510 --><!--line 0 --><!--description Y2hvcmU6IHJlZmFjdG9yIGZvciBBY3Rpb25zIERvbmUgTm90aWZpY2F0aW9u-->chore: refactor for Actions Done Notification<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7505): <!--number 7505 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvdG9vbHMvY21kL2RlYWRjb2RlIHRvIHYwLjMyLjAgKGZvcmdlam8p-->Update module golang.org/x/tools/cmd/deadcode to v0.32.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7504): <!--number 7504 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvbmV0IHRvIHYwLjM5LjAgKGZvcmdlam8p-->Update module golang.org/x/net to v0.39.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7503): <!--number 7503 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kga2F0ZXggdG8gdjAuMTYuMjIgKGZvcmdlam8p-->Update dependency katex to v0.16.22 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7499): <!--number 7499 --><!--line 0 --><!--description Y2hvcmUoaTE4bik6IHVwZGF0ZSBjb250cmlidXRpbmcgZG9jdW1lbnRhdGlvbiB3aXRoIEpTT04gZm9ybWF0-->chore(i18n): update contributing documentation with JSON format<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7497): <!--number 7497 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvaW1hZ2UgdG8gdjAuMjYuMCAoZm9yZ2Vqbyk=-->Update module golang.org/x/image to v0.26.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7495): <!--number 7495 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21pbmlvL21pbmlvLWdvL3Y3IHRvIHY3LjAuOTAgKGZvcmdlam8p-->Update module github.com/minio/minio-go/v7 to v7.0.90 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7494): <!--number 7494 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgd2VicGFjayB0byB2NS45OS41IChmb3JnZWpvKQ==-->Update dependency webpack to v5.99.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7491): <!--number 7491 --><!--line 0 --><!--description QWN0aW9ucyBEb25lIE5vdGlmaWNhdGlvbg==-->Actions Done Notification<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7490): <!--number 7490 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgd2VicGFjayB0byB2NS45OS4xIChmb3JnZWpvKQ==-->Update dependency webpack to v5.99.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7488): <!--number 7488 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnby51YmVyLm9yZy9tb2NrIHRvIHYwLjUuMSAoZm9yZ2Vqbyk=-->Update module go.uber.org/mock to v0.5.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7486): <!--number 7486 --><!--line 0 --><!--description W2dpdGVhXSB3ZWVrIDIwMjUtMTQgY2hlcnJ5IHBpY2sgKGdpdGVhL21haW4gLT4gZm9yZ2Vqbyk=-->[gitea] week 2025-14 cherry pick (gitea/main -> forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7485): <!--number 7485 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvY3J5cHRvIHRvIHYwLjM3LjAgKGZvcmdlam8p-->Update module golang.org/x/crypto to v0.37.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7484): <!--number 7484 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHYzOS4yMzMuNSAoZm9yZ2Vqbyk=-->Update renovate to v39.233.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7479): <!--number 7479 --><!--line 0 --><!--description TWlub3IgZ3JhbW1hdGljYWwgZml4IHRvIHJ1bm5lciBkZWxldGlvbiBtZXNzYWdl-->Minor grammatical fix to runner deletion message<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7475): <!--number 7475 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvb2F1dGgyIHRvIHYwLjI5LjAgKGZvcmdlam8p-->Update module golang.org/x/oauth2 to v0.29.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7473): <!--number 7473 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2Zzbm90aWZ5L2Zzbm90aWZ5IHRvIHYxLjkuMCAoZm9yZ2Vqbyk=-->Update module github.com/fsnotify/fsnotify to v1.9.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7472): <!--number 7472 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgY2xpcHBpZSB0byB2NC4xLjYgKGZvcmdlam8p-->Update dependency clippie to v4.1.6 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7471): <!--number 7471 --><!--line 0 --><!--description Zml4KHVpKTogZW5zdXJlIGRpbW1lciBhbHdheXMgY292ZXJzIHdob2xlIHBhZ2U=-->fix(ui): ensure dimmer always covers whole page<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7470): <!--number 7470 --><!--line 0 --><!--description Zml4KHVpKTogb25seSBydW4gYXV0aF9uYW1lIGNvZGUgb24gbmV3IGFuZCBlZGl0IHBhZ2U=-->fix(ui): only run auth_name code on new and edit page<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7469): <!--number 7469 --><!--line 0 --><!--description Y2hvcmUocmVsZWFzZS1ub3Rlcyk6IEZvcmdlam8gdjExLjAuMA==-->chore(release-notes): Forgejo v11.0.0<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7468): <!--number 7468 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2JsZXZlc2VhcmNoL2JsZXZlL3YyIHRvIHYyLjUuMCAoZm9yZ2Vqbyk=-->Update module github.com/blevesearch/bleve/v2 to v2.5.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7467): <!--number 7467 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgdHlwZXNjcmlwdCB0byB2NS44LjMgKGZvcmdlam8p-->Update dependency typescript to v5.8.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7465): <!--number 7465 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgYW5zaV91cCB0byB2Ni4wLjUgKGZvcmdlam8p-->Update dependency ansi_up to v6.0.5 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7463): <!--number 7463 --><!--line 0 --><!--description Y2hvcmU6IGFsd2F5cyBlbmFibGUgd2VicGFjayBwcm9ncmVzcw==-->chore: always enable webpack progress<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7462): <!--number 7462 --><!--line 0 --><!--description Y2hvcmUoaTE4bik6IGFkZCBhIG1ldGEgbGluZSB0byB0aGUgYmFzZSBqc29uIHRyYW5zbGF0aW9u-->chore(i18n): add a meta line to the base json translation<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7459): <!--number 7459 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2FsZWN0aG9tYXMvY2hyb21hL3YyIHRvIHYyLjE2LjAgKGZvcmdlam8p-->Update module github.com/alecthomas/chroma/v2 to v2.16.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7458): <!--number 7458 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBjb2RlLmdpdGVhLmlvL3Nkay9naXRlYSB0byB2MC4yMS4wIChmb3JnZWpvKQ==-->Update module code.gitea.io/sdk/gitea to v0.21.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7456): <!--number 7456 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgYW5zaV91cCB0byB2Ni4wLjMgKGZvcmdlam8p-->Update dependency ansi_up to v6.0.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7455): <!--number 7455 --><!--line 0 --><!--description TWFrZWZpbGUgJiBCU0RtYWtlZmlsZSBjaGFuZ2Vz-->Makefile & BSDmakefile changes<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7453): <!--number 7453 --><!--line 0 --><!--description Y2hvcmUoc2VjKTogdW5pZnkgdXNhZ2Ugb2YgYGNyeXB0by9yYW5kLlJlYWRg-->chore(sec): unify usage of `crypto/rand.Read`<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7452): <!--number 7452 --><!--line 0 --><!--description bWFrZSBpbnN0YWxsaW5nIEZvcmdlam8gd29yayBhZ2Fpbg==-->make installing Forgejo work again<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7451): <!--number 7451 --><!--line 0 --><!--description Y2hvcmUoaTE4bik6IGNsZWFudXAgYHNldHRpbmdzLmFkb3B0YCBzdHJpbmc=-->chore(i18n): cleanup `settings.adopt` string<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7434): <!--number 7434 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21hdHRuL2dvLXNxbGl0ZTMgdG8gdjEuMTQuMjcgKGZvcmdlam8p-->Update module github.com/mattn/go-sqlite3 to v1.14.27 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7433): <!--number 7433 --><!--line 0 --><!--description ZmVhdChidWlsZCk6IHJ1biBsaW50LWxvY2FsZS11c2FnZSB3L28gLS1hbGxvdy1taXNzaW5nLW1zZ2lkcw==-->feat(build): run lint-locale-usage w/o --allow-missing-msgids<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7431): <!--number 7431 --><!--line 0 --><!--description bWFrZSByZXBvIGNsb25lIGh0dHBzL3NzaCBsaXN0ZW5lciBjb25kaXRpb25hbA==-->make repo clone https/ssh listener conditional<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7429): <!--number 7429 --><!--line 0 --><!--description ZmVhdChidWlsZCk6IHVuaWZvcm0gaW5pIHBhcnNpbmc=-->feat(build): uniform ini parsing<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7425): <!--number 7425 --><!--line 0 --><!--description ZmVhdChsb2NhbGUgSXRlcik6IHByb3Blcmx5IHN1cHBvcnQgdHJQbHVyYWxTdHJpbmc=-->feat(locale Iter): properly support trPluralString<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7424): <!--number 7424 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL21hdHRuL2dvLXNxbGl0ZTMgdG8gdjEuMTQuMjUgKGZvcmdlam8p-->Update module github.com/mattn/go-sqlite3 to v1.14.25 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7423): <!--number 7423 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvLXdlYmF1dGhuL3dlYmF1dGhuIHRvIHYwLjEyLjMgKGZvcmdlam8p-->Update module github.com/go-webauthn/webauthn to v0.12.3 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7422): <!--number 7422 --><!--line 0 --><!--description Zml4KGkxOG4pOiBmaXggc2V2ZXJhbCB1c2FnZXMgb2YgaTE4bg==-->fix(i18n): fix several usages of i18n<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7421): <!--number 7421 --><!--line 0 --><!--description Zml4KG1pZ3JhdGlvbnMpOiB0cmFuc2ZlciBQUiBmbG93IGluZm9ybWF0aW9u-->fix(migrations): transfer PR flow information<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7419): <!--number 7419 --><!--line 0 --><!--description Y2hvcmU6IGFkZCBlbXB0eSBgYWN0aW9uX3ZhcmlhYmxlYCBmaXh0dXJl-->chore: add empty `action_variable` fixture<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7417): <!--number 7417 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjQuMiAoZm9yZ2Vqbyk=-->Update dependency go to v1.24.2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7416): <!--number 7416 --><!--line 0 --><!--description Y2hvcmUodWkpOiByZW1vdmUgZm9tYW50aWMncyBkaW1tZXIgbW9kdWxl-->chore(ui): remove fomantic's dimmer module<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7414): <!--number 7414 --><!--line 0 --><!--description Y2hvcmUodWkpOiByZW1vdmUgaW5lZmZlY3RpdmUgY2xhc3Mgc21hbGwgaW4gaW5saW5lIGNvZGUgcHJldmlldw==-->chore(ui): remove ineffective class small in inline code preview<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7408): <!--number 7408 --><!--line 0 --><!--description Y2hvcmU6IGVuYWJsZSBzZXZlcmFsIG5vLWpxdWVyeSBydWxlcw==-->chore: enable several no-jquery rules<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7407): <!--number 7407 --><!--line 0 --><!--description VXBkYXRlIHZpdGVzdCBtb25vcmVwbyB0byB2My4xLjEgKGZvcmdlam8p-->Update vitest monorepo to v3.1.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7406): <!--number 7406 --><!--line 0 --><!--description VXBkYXRlIGxpbnRlcnMgdG8gdjguMjkuMCAoZm9yZ2Vqbyk=-->Update linters to v8.29.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7400): <!--number 7400 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7399): <!--number 7399 --><!--line 0 --><!--description VXBkYXRlIHJlbm92YXRlIHRvIHYzOS4yMjIuMSAoZm9yZ2Vqbyk=-->Update renovate to v39.222.1 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7397): <!--number 7397 --><!--line 0 --><!--description W2dpdGVhXSB3ZWVrIDIwMjUtMTMgY2hlcnJ5IHBpY2sgKGdpdGVhL21haW4gLT4gZm9yZ2Vqbyk=-->[gitea] week 2025-13 cherry pick (gitea/main -> forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7396): <!--number 7396 --><!--line 0 --><!--description Y2hvcmU6IHVzZSBkeW5hbWljIGlk-->chore: use dynamic id<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7394): <!--number 7394 --><!--line 0 --><!--description dXNlIGNvcnJlY3QgaW5pdCBpbnN0cnVjdGlvbiBmb3Igc2hhMjU2-->use correct init instruction for sha256<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7392): <!--number 7392 --><!--line 0 --><!--description TG9jayBmaWxlIG1haW50ZW5hbmNlIChmb3JnZWpvKQ==-->Lock file maintenance (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7391): <!--number 7391 --><!--line 0 --><!--description VXBkYXRlIGdpdGh1Yi5jb20vZ29vZ2xlL3Bwcm9mIGRpZ2VzdCB0byBhNGIwM2VjIChmb3JnZWpvKQ==-->Update github.com/google/pprof digest to a4b03ec (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7390): <!--number 7390 --><!--line 0 --><!--description QWNjZXNzaWJpbGl0eTogZml4IHVucmVhZGFibGUgY2FwdGNoYSB3aXRoIGRhcmsgdGhlbWVz-->Accessibility: fix unreadable captcha with dark themes<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7384): <!--number 7384 --><!--line 0 --><!--description VXBkYXRlIGxpbnRlcnMgKGZvcmdlam8p-->Update linters (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7383): <!--number 7383 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgeWFtbGxpbnQgdG8gdjEuMzcuMCAoZm9yZ2Vqbyk=-->Update dependency yamllint to v1.37.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7382): <!--number 7382 --><!--line 0 --><!--description VXBkYXRlIHZpdGVzdCBtb25vcmVwbyB0byB2My4wLjkgKGZvcmdlam8p-->Update vitest monorepo to v3.0.9 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7381): <!--number 7381 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgQHZpdGVzdC9lc2xpbnQtcGx1Z2luIHRvIHYxLjEuMzggKGZvcmdlam8p-->Update dependency @vitest/eslint-plugin to v1.1.38 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7379): <!--number 7379 --><!--line 0 --><!--description cHJlcGVuZCBBcHBTdWJVUkwgdG8gdmlzaWJpbGl0eSBoaW50IFVSTHM=-->prepend AppSubURL to visibility hint URLs<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7378): <!--number 7378 --><!--line 0 --><!--description Y2hvcmU6IGltcHJvdmUgcmVwbyBtaWdyYXRlIGUyZSB0ZXN0-->chore: improve repo migrate e2e test<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7376): <!--number 7376 --><!--line 0 --><!--description Y2hvcmUodGVzdHMpOiBmaXggdGVzdGluZyBmYWlsdXJlIGNhdXNlZCBieSBkZXAgdXBkYXRl-->chore(tests): fix testing failure caused by dep update<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7374): <!--number 7374 --><!--line 0 --><!--description Y2hvcmUodGVzdHMpOiByZWZhY3RvciBtaWdyYXRpb24gZm9ybSB0ZXN0-->chore(tests): refactor migration form test<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7372): <!--number 7372 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZXNsaW50LXBsdWdpbi11bmljb3JuIHRvIHY1OCAoZm9yZ2Vqbyk=-->Update dependency eslint-plugin-unicorn to v58 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7371): <!--number 7371 --><!--line 0 --><!--description Y2hvcmU6IHVzZSBjb3JyZWN0IGltcG9ydA==-->chore: use correct import<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7367): <!--number 7367 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZ2NpL2dvbGFuZ2NpLWxpbnQvY21kL2dvbGFuZ2NpLWxpbnQgdG8gdjIgKGZvcmdlam8p-->Update module github.com/golangci/golangci-lint/cmd/golangci-lint to v2 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7366): <!--number 7366 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy90ai1hY3Rpb25zL2NoYW5nZWQtZmlsZXMgYWN0aW9uIHRvIHY0NiAoZm9yZ2Vqbyk=-->Update https://data.forgejo.org/tj-actions/changed-files action to v46 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7362): <!--number 7362 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvbmV0IHRvIHYwLjM4LjAgKGZvcmdlam8p-->Update module golang.org/x/net to v0.38.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7356): <!--number 7356 --><!--line 0 --><!--description Zml4KHVpKTogaW1wcm92ZSB2ZXJ0aWNhbCBhbGlnbm1lbnQgb2YgaWNvbnMgd2l0aCB0ZXh0IGluIHRoZSBvdmVyZmxvdyBtZW51ICgjNzMxNCk=-->fix(ui): improve vertical alignment of icons with text in the overflow menu (#7314)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7355): <!--number 7355 --><!--line 0 --><!--description NDEwOC1lbXB0eS1zbGljZS1lbmNvZGVkLXRvLW51bGw=-->4108-empty-slice-encoded-to-null<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7350): <!--number 7350 --><!--line 0 --><!--description cmVmYWN0b3IoY2xpKTogaW1wcm92ZSBkdW1wJ3MgdGVtcG9yYXJ5IGZpbGUgaGFuZGxpbmc=-->refactor(cli): improve dump's temporary file handling<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7348): <!--number 7348 --><!--line 0 --><!--description aW50cm9kdWNlIGdpdE5lZWRlZCBib29sIGluIHNldHVw-->introduce gitNeeded bool in setup<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7344): <!--number 7344 --><!--line 0 --><!--description Zml4KHVpKTogRG8gbm90IGNoZWNrIGZvciBgdmVydGljYWwtYWxpZ25g-->fix(ui): Do not check for `vertical-align`<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7339): <!--number 7339 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgbWVybWFpZCB0byB2MTEuNi4wIChmb3JnZWpvKQ==-->Update dependency mermaid to v11.6.0 (forgejo)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7337): <!--number 7337 --><!--line 0 --><!--description Y2hvcmU6IGJyYW5kaW5nIGltcG9ydCBwYXRo-->chore: branding import path<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7314): <!--number 7314 --><!--line 0 --><!--description Zml4KHVpKTogaW1wcm92ZSB2ZXJ0aWNhbCBhbGlnbm1lbnQgb2YgaWNvbnMgd2l0aCB0ZXh0IGluIHRoZSBvdmVyZmxvdyBtZW51-->fix(ui): improve vertical alignment of icons with text in the overflow menu<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7278): <!--number 7278 --><!--line 0 --><!--description ZmVhdChidWlsZCk6IGxpbnQtbG9jYWxlLXVzYWdlIHNob3VsZCBkZXRlY3QgbW9yZSBUciBmdW5jdGlvbnM=-->feat(build): lint-locale-usage should detect more Tr functions<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7271): <!--number 7271 --><!--line 0 --><!--description ZmVhdCh1aSk6IGltcHJvdmUgYnV0dG9uIGdhcCBjb25zaXN0ZW5jeSwgbWFrZSBpdCB2YXJpYWJsZSwgbGFyZ2VyIG9uIHRvdWNoc2NyZWVucw==-->feat(ui): improve button gap consistency, make it variable, larger on touchscreens<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7261): <!--number 7261 --><!--line 0 --><!--description cmVkaXJlY3QgdG8gc3VibW9kdWxlIGluc3RlYWQgb2YgdGhyb3dpbmcgNTAwIGVycm9yIHdoZW4gdmlld2luZyBzdWJtb2R1bGUgZW50cnk=-->redirect to submodule instead of throwing 500 error when viewing submodule entry<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7203): <!--number 7203 --><!--line 0 --><!--description YWRkIHBvcnQgYW5kIHNjaGVtYSB0byBmZWRlcmF0aW9uIGhvc3Q=-->add port and schema to federation host<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7092): <!--number 7092 --><!--line 0 --><!--description ZmVhdChyZXBvLGxvY2FsZSk6IG1lcmdlIFBSL2lzc3VlcyBjYXNlcyBmb3Igc29tZSByZXBvL2lzc3VlIHN0cmluZ3M=-->feat(repo,locale): merge PR/issues cases for some repo/issue strings<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7035): <!--number 7035 --><!--line 0 --><!--description ZW5hYmxlIEhUVFAgc2lnbmF0dXJlcyBvbiBhbGwgQWN0aXZpdHlQdWIgZW5kcG9pbnRz-->enable HTTP signatures on all ActivityPub endpoints<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6977): <!--number 6977 --><!--line 0 --><!--description ZmVhdCE6IEFidXNpdmUgY29udGVudCByZXBvcnRpbmc=-->feat!: Abusive content reporting<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6154): <!--number 6154 --><!--line 0 --><!--description UmVwbGFjZSB0aGUgJ3JlbGF0aXZlLXRpbWUnIGVsZW1lbnQgc2NyaXB0aW5nIHdpdGggY3VzdG9tLCB0cmFuc2xhdGFibGUgcmV3cml0ZQ==-->Replace the 'relative-time' element scripting with custom, translatable rewrite<!--description-->
|
||||
- Already announced in the release notes of an older stable release
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8234): <!--number 8234 --><!--line 0 --><!--description Y29sbGFib3JhdG9yIGNhbiBlZGl0IHdpa2kgd2l0aCB3cml0ZSBhY2Nlc3M=-->collaborator can edit wiki with write access<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8189): <!--number 8189 --><!--line 0 --><!--description ZG8gbm90IGlnbm9yZSBhdXRvbWVyZ2Ugd2hpbGUgYSBQUiBpcyBjaGVja2luZyBmb3IgY29uZmxpY3Rz-->do not ignore automerge while a PR is checking for conflicts<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8170): <!--number 8170 --><!--line 0 --><!--description ZXJyb25lb3VzIGxpc3QgY29udGludWF0aW9uIG9uIENtZCtFbnRlciAoIzgxNTMp-->erroneous list continuation on Cmd+Enter (#8153)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/8155): <!--number 8155 --><!--line 0 --><!--description ZG8gbm90IGZhaWwgd2hlbiByZWxlYXNlIG9yIHdpa2kgaXMgc2V0IGluIGAvcmVwb3MvbWlncmF0ZWAgQVBJ-->do not fail when release or wiki is set in `/repos/migrate` API<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7979): <!--number 7979 --><!--line 0 --><!--description cHVsbCByZXF1ZXN0IGNyb3NzIHJlZmVyZW5jZXM=-->pull request cross references<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7976): <!--number 7976 --><!--line 0 --><!--description aWdub3JlIGV4cGlyZWQgYXJ0aWZhY3RzIGZvciBxdW90YSBjYWxjdWxhdGlvbg==-->ignore expired artifacts for quota calculation<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7883): <!--number 7883 --><!--line 0 --><!--description cXVvdGUgcmVwbHkgaW4gQ2hyb21pdW0=-->quote reply in Chromium<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7775): <!--number 7775 --><!--line 0 --><!--description bWFrZSBoYXNoIHBhdHRlcm4gbW9yZSBzdHJpY3Q=-->make hash pattern more strict<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7755): <!--number 7755 --><!--line 0 --><!--description Zml4KHNlYyk6IGFkZCB0ZXN0cyBmb3IgT0F1dGgyIHNpZ251cA==-->fix(sec): add tests for OAuth2 signup<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7752): <!--number 7752 --><!--line 0 --><!--description Zml4KHNlYyk6IG9ubHkgZGVncmFkZSBwZXJtaXNzaW9uIGNoZWNrIGZvciBnaXQgcHVzaA==-->fix(sec): only degrade permission check for git push<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7650): <!--number 7650 --><!--line 0 --><!--description ZGlzcGxheSB0aGUgbGlzdCBvZiB0YXNrcyBpbiB0aGUgcnVubmVyIGVkaXQgcGFnZQ==-->display the list of tasks in the runner edit page<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7594): <!--number 7594 --><!--line 0 --><!--description Zml4KGkxOG4pOiBwcmV2ZW50IGluY29ycmVjdCBsb2dnaW5nIG9uIHN0cmluZ3MgbWlzc2luZyBpbiBKU09OIGxvY2FsZXM=-->fix(i18n): prevent incorrect logging on strings missing in JSON locales<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7584): <!--number 7584 --><!--line 0 --><!--description Zml4KHVpL3ByKTogdXNlIGV5ZSBpY29uIGZvciByZXZpZXdz-->fix(ui/pr): use eye icon for reviews<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7581): <!--number 7581 --><!--line 0 --><!--description Zml4KHVpKTogdXNlIGdhcCBpbiBzd2l0Y2ggaXRlbXM=-->fix(ui): use gap in switch items<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7395): <!--number 7395 --><!--line 0 --><!--description dmFsaWRhdGUgaW5wdXQgZm9yIGRlZmF1bHRfe21lcmdlLHVwZGF0ZX1fc3R5bGU=-->validate input for default_{merge,update}_style<!--description-->
|
||||
<!--end release-notes-assistant-->
|
|
@ -8,7 +8,8 @@
|
|||
],
|
||||
"baseBranches": [
|
||||
"$default",
|
||||
"/^v11\\.\\d+/forgejo$/"
|
||||
"/^v11\\.\\d+/forgejo$/",
|
||||
"/^v12\\.\\d+/forgejo$/"
|
||||
],
|
||||
"postUpdateOptions": ["gomodTidy", "gomodUpdateImportPaths", "npmDedupe"],
|
||||
"prConcurrentLimit": 10,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 = ""
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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...)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,7 +42,7 @@ func isExcludedEntry(entry *git.TreeEntry) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
if entry.IsSubModule() {
|
||||
if entry.IsSubmodule() {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div id="insert-timeline" hx-swap-oob="beforebegin">
|
||||
{{template "repo/issue/view_content/comments" .}}
|
||||
</div>
|
||||
{{template "repo/issue/view_content/sidebar/milestones" .}}
|
||||
{{template "repo/issue/milestone/selected" .}}
|
||||
|
|
11
templates/repo/issue/milestone/selected.tmpl
Normal file
11
templates/repo/issue/milestone/selected.tmpl
Normal file
|
@ -0,0 +1,11 @@
|
|||
<div id="selected-milestone" class="ui select-milestone list">
|
||||
<span class="no-select item {{if .Issue.Milestone}}tw-hidden{{end}}">{{ctx.Locale.Tr "repo.issues.new.no_milestone"}}</span>
|
||||
<div class="selected">
|
||||
{{if .Issue.Milestone}}
|
||||
<a class="item muted sidebar-item-link" href="{{.RepoLink}}/milestone/{{.Issue.Milestone.ID}}">
|
||||
{{svg "octicon-milestone" 18 "tw-mr-2"}}
|
||||
{{.Issue.Milestone.Name}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
|
@ -1,4 +1,4 @@
|
|||
<div id="milestone-section" hx-swap="morph" hx-target="this" hx-indicator="this">
|
||||
<div id="milestone-section" hx-swap="morph" hx-target="#selected-milestone" hx-indicator="this">
|
||||
<div class="ui {{if or (not .HasIssuesOrPullsWritePermission) .Repository.IsArchived}}disabled{{end}} floating jump select-milestone dropdown">
|
||||
<a class="text muted flex-text-block">
|
||||
<strong>{{ctx.Locale.Tr "repo.issues.new.milestone"}}</strong>
|
||||
|
@ -10,15 +10,5 @@
|
|||
{{template "repo/issue/milestone/select_menu" .}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui select-milestone list">
|
||||
<span class="no-select item {{if .Issue.Milestone}}tw-hidden{{end}}">{{ctx.Locale.Tr "repo.issues.new.no_milestone"}}</span>
|
||||
<div class="selected">
|
||||
{{if .Issue.Milestone}}
|
||||
<a class="item muted sidebar-item-link" href="{{.RepoLink}}/milestone/{{.Issue.Milestone.ID}}">
|
||||
{{svg "octicon-milestone" 18 "tw-mr-2"}}
|
||||
{{.Issue.Milestone.Name}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{template "repo/issue/milestone/selected" .}}
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
<div class="ui equal width compact grid">
|
||||
<div class="ui reference">
|
||||
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}}
|
||||
<div class="row tw-items-center" data-tooltip-content="{{$issueReferenceLink}}">
|
||||
<span class="text column truncate">{{ctx.Locale.Tr "repo.issues.reference_link" $issueReferenceLink}}</span>
|
||||
<button class="ui two wide button column tw-p-2" data-clipboard-text="{{$issueReferenceLink}}">{{svg "octicon-copy" 14}}</button>
|
||||
<span class="text">
|
||||
<strong>
|
||||
{{ctx.Locale.Tr "discussion.sidebar.reference"}}
|
||||
</strong>
|
||||
</span>
|
||||
<div class="ui equal width compact grid">
|
||||
<div class="row tw-items-center" data-tooltip-content="{{$issueReferenceLink}}">
|
||||
<span class="text column truncate">{{$issueReferenceLink}}</span>
|
||||
<button class="ui two wide button column tw-p-2" data-clipboard-text="{{$issueReferenceLink}}">{{svg "octicon-copy" 14}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -292,7 +292,7 @@
|
|||
<div class="field {{if .Err_PushMirrorBranchFilter}}error{{end}}">
|
||||
<label for="push_mirror_branch_filter">{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.label"}}</label>
|
||||
<input id="push_mirror_branch_filter" name="push_mirror_branch_filter" value="{{.push_mirror_branch_filter}}" maxlength="2048">
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "forgejo"}}</p>
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "Forgejo"}}</p>
|
||||
</div>
|
||||
<details class="ui optional field" {{if or .Err_PushMirrorAuth .push_mirror_username}}open{{end}}>
|
||||
<summary class="tw-p-1">
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<div class="ui small input">
|
||||
<input id="push-mirror-edit-branch-filter" name="push_mirror_branch_filter" maxlength="2048">
|
||||
</div>
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "forgejo"}}</p>
|
||||
<p class="help">{{ctx.Locale.Tr "repo.settings.push_mirror.branch_filter.description" "https://forgejo.org/docs/latest/user/repo-mirror/#branch-filter" "Forgejo"}}</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="ui small basic cancel button">
|
||||
|
|
|
@ -20,17 +20,17 @@
|
|||
{{range $item := .Files}}
|
||||
{{$entry := $item.Entry}}
|
||||
{{$commit := $item.Commit}}
|
||||
{{$subModuleFile := $item.SubModuleFile}}
|
||||
<tr data-entryname="{{$entry.Name}}" data-ready="{{if $commit}}true{{else}}false{{end}}" class="{{if not $commit}}not{{end}}ready entry">
|
||||
<td class="name four wide">
|
||||
<span class="truncate">
|
||||
{{if $entry.IsSubModule}}
|
||||
{{$refURL := $subModuleFile.RefURL AppUrl $.Repository.FullName $.SSHDomain}} {{/* FIXME: the usage of AppUrl seems incorrect, it would be fixed in the future, use AppSubUrl instead */}}
|
||||
{{if $entry.IsSubmodule}}
|
||||
{{$submodule := $item.Submodule}}
|
||||
{{$refURL := $submodule.ResolveUpstreamURL $.Repository.HTMLURL}}
|
||||
{{$icon := (svg "octicon-file-submodule" 16 "tw-mr-2")}}
|
||||
{{if $refURL}}
|
||||
<a class="muted" href="{{$refURL}}">{{$icon}}{{$entry.Name}}</a><span class="at">@</span><a href="{{$refURL}}/commit/{{PathEscape $subModuleFile.RefID}}">{{ShortSha $subModuleFile.RefID}}</a>
|
||||
<a class="muted" href="{{$refURL}}">{{$icon}}{{$entry.Name}}</a><span class="at">@</span><a href="{{$refURL}}/commit/{{PathEscape $submodule.Commit.String}}">{{ShortSha $submodule.Commit.String}}</a>
|
||||
{{else}}
|
||||
{{$icon}}{{$entry.Name}}<span class="at">@</span>{{ShortSha $subModuleFile.RefID}}
|
||||
{{$icon}}{{$entry.Name}}<span class="at">@</span>{{ShortSha $submodule.Commit.String}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if $entry.IsDir}}
|
||||
|
|
|
@ -83,6 +83,22 @@ func DeclareGitRepos(t *testing.T) func() {
|
|||
Filename: "a-file",
|
||||
Versions: []string{"{a}{а}"},
|
||||
}}, nil),
|
||||
newRepo(t, 2, "multiple-combo-boxes", nil, []FileChanges{{
|
||||
Filename: ".forgejo/issue_template/multi-combo-boxes.yaml",
|
||||
Versions: []string{`
|
||||
name: "Multiple combo-boxes"
|
||||
description: "To show something"
|
||||
body:
|
||||
- type: textarea
|
||||
id: textarea-one
|
||||
attributes:
|
||||
label: one
|
||||
- type: textarea
|
||||
id: textarea-two
|
||||
attributes:
|
||||
label: two
|
||||
`},
|
||||
}}, nil),
|
||||
newRepo(t, 11, "dependency-test", &tests.DeclarativeRepoOptions{
|
||||
UnitConfig: optional.Some(map[unit_model.Type]convert.Conversion{
|
||||
unit_model.TypeIssues: &repo_model.IssuesConfig{
|
||||
|
|
|
@ -221,7 +221,7 @@ test('Issue: Milestone', async ({page}, workerInfo) => {
|
|||
const response = await page.goto('/user2/repo1/issues/1');
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
const selectedMilestone = page.locator('.issue-content-right .select-milestone.list');
|
||||
const selectedMilestone = page.locator('.issue-content-right #selected-milestone');
|
||||
const milestoneDropdown = page.locator('.issue-content-right .select-milestone.dropdown');
|
||||
await expect(selectedMilestone).toContainText('No milestone');
|
||||
|
||||
|
|
|
@ -456,3 +456,62 @@ test('Combo Markdown: preview mode switch', async ({page}) => {
|
|||
await expect(previewPanel).toBeHidden();
|
||||
await save_visual(page);
|
||||
});
|
||||
|
||||
test('Multiple combo markdown: insert table', async ({page}) => {
|
||||
const response = await page.goto('/user2/multiple-combo-boxes/issues/new?template=.forgejo%2fissue_template%2fmulti-combo-boxes.yaml');
|
||||
expect(response?.status()).toBe(200);
|
||||
|
||||
// check that there are two textareas
|
||||
const textareaOne = page.locator('textarea[name=form-field-textarea-one]');
|
||||
const comboboxOne = page.locator('textarea#_combo_markdown_editor_0');
|
||||
await expect(textareaOne).toBeVisible();
|
||||
await expect(comboboxOne).toBeHidden();
|
||||
const textareaTwo = page.locator('textarea[name=form-field-textarea-two]');
|
||||
const comboboxTwo = page.locator('textarea#_combo_markdown_editor_1');
|
||||
await expect(textareaTwo).toBeVisible();
|
||||
await expect(comboboxTwo).toBeHidden();
|
||||
|
||||
// focus first one and add table to it
|
||||
await textareaOne.click();
|
||||
await expect(comboboxOne).toBeVisible();
|
||||
await expect(comboboxTwo).toBeHidden();
|
||||
|
||||
const newTableButtonOne = page.locator('[for="_combo_markdown_editor_0"] button[data-md-action="new-table"]');
|
||||
await newTableButtonOne.click();
|
||||
|
||||
const newTableModalOne = page.locator('div[data-markdown-table-modal-id="0"]');
|
||||
await expect(newTableModalOne).toBeVisible();
|
||||
|
||||
await newTableModalOne.locator('input[name="table-rows"]').fill('3');
|
||||
await newTableModalOne.locator('input[name="table-columns"]').fill('2');
|
||||
|
||||
await newTableModalOne.locator('button[data-selector-name="ok-button"]').click();
|
||||
|
||||
await expect(newTableModalOne).toBeHidden();
|
||||
|
||||
await expect(comboboxOne).toHaveValue('| Header | Header |\n|---------|---------|\n| Content | Content |\n| Content | Content |\n| Content | Content |\n');
|
||||
await expect(comboboxTwo).toBeEmpty();
|
||||
await save_visual(page);
|
||||
|
||||
// focus second one and add table to it
|
||||
await textareaTwo.click();
|
||||
await expect(comboboxOne).toBeHidden();
|
||||
await expect(comboboxTwo).toBeVisible();
|
||||
|
||||
const newTableButtonTwo = page.locator('[for="_combo_markdown_editor_1"] button[data-md-action="new-table"]');
|
||||
await newTableButtonTwo.click();
|
||||
|
||||
const newTableModalTwo = page.locator('div[data-markdown-table-modal-id="1"]');
|
||||
await expect(newTableModalTwo).toBeVisible();
|
||||
|
||||
await newTableModalTwo.locator('input[name="table-rows"]').fill('2');
|
||||
await newTableModalTwo.locator('input[name="table-columns"]').fill('3');
|
||||
|
||||
await newTableModalTwo.locator('button[data-selector-name="ok-button"]').click();
|
||||
|
||||
await expect(newTableModalTwo).toBeHidden();
|
||||
|
||||
await expect(comboboxOne).toHaveValue('| Header | Header |\n|---------|---------|\n| Content | Content |\n| Content | Content |\n| Content | Content |\n');
|
||||
await expect(comboboxTwo).toHaveValue('| Header | Header | Header |\n|---------|---------|---------|\n| Content | Content | Content |\n| Content | Content | Content |\n');
|
||||
await save_visual(page);
|
||||
});
|
||||
|
|
|
@ -784,47 +784,66 @@ func TestPullRequestStaleReview(t *testing.T) {
|
|||
)
|
||||
defer f()
|
||||
|
||||
// Clone it.
|
||||
dstPath := t.TempDir()
|
||||
r := fmt.Sprintf("%suser2/%s.git", u.String(), repo.Name)
|
||||
cloneURL, _ := url.Parse(r)
|
||||
cloneURL.User = url.UserPassword("user2", userPassword)
|
||||
require.NoError(t, git.CloneWithArgs(t.Context(), nil, cloneURL.String(), dstPath, git.CloneRepoOptions{}))
|
||||
clone := func(t *testing.T, clone string) string {
|
||||
t.Helper()
|
||||
|
||||
// Create first commit.
|
||||
require.NoError(t, os.WriteFile(path.Join(dstPath, "README.md"), []byte("## test content"), 0o600))
|
||||
require.NoError(t, git.AddChanges(dstPath, true))
|
||||
require.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||
Committer: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Author: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Message: "Add README.",
|
||||
}))
|
||||
stdout := &bytes.Buffer{}
|
||||
require.NoError(t, git.NewCommand(t.Context(), "rev-parse", "HEAD").Run(&git.RunOpts{Dir: dstPath, Stdout: stdout}))
|
||||
firstCommitID := strings.TrimSpace(stdout.String())
|
||||
dstPath := t.TempDir()
|
||||
cloneURL, _ := url.Parse(clone)
|
||||
cloneURL.User = url.UserPassword("user2", userPassword)
|
||||
require.NoError(t, git.CloneWithArgs(t.Context(), nil, cloneURL.String(), dstPath, git.CloneRepoOptions{}))
|
||||
|
||||
// Create agit PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
|
||||
return dstPath
|
||||
}
|
||||
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Index: 1, BaseRepoID: repo.ID})
|
||||
firstCommit := func(t *testing.T, dstPath string) string {
|
||||
t.Helper()
|
||||
|
||||
req := NewRequest(t, "GET", "/"+repo.FullName()+"/pulls/1/files/reviews/new_comment")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
require.NoError(t, os.WriteFile(path.Join(dstPath, "README.md"), []byte("## test content"), 0o600))
|
||||
require.NoError(t, git.AddChanges(dstPath, true))
|
||||
require.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||
Committer: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Author: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Message: "Add README.",
|
||||
}))
|
||||
stdout := &bytes.Buffer{}
|
||||
require.NoError(t, git.NewCommand(t.Context(), "rev-parse", "HEAD").Run(&git.RunOpts{Dir: dstPath, Stdout: stdout}))
|
||||
|
||||
t.Run("Mark review as stale", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
return strings.TrimSpace(stdout.String())
|
||||
}
|
||||
|
||||
// Create a approved review against against this commit.
|
||||
req = NewRequestWithValues(t, "POST", "/"+repo.FullName()+"/pulls/1/files/reviews/comments", map[string]string{
|
||||
secondCommit := func(t *testing.T, dstPath string) {
|
||||
require.NoError(t, os.WriteFile(path.Join(dstPath, "README.md"), []byte("## I prefer this heading"), 0o600))
|
||||
require.NoError(t, git.AddChanges(dstPath, true))
|
||||
require.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||
Committer: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Author: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Message: "Add README.",
|
||||
}))
|
||||
}
|
||||
|
||||
firstReview := func(t *testing.T, firstCommitID string, index int64) {
|
||||
t.Helper()
|
||||
|
||||
resp := session.MakeRequest(t, NewRequest(t, "GET", fmt.Sprintf("/%s/pulls/%d/files/reviews/new_comment", repo.FullName(), index)), http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/pulls/%d/files/reviews/comments", repo.FullName(), index), map[string]string{
|
||||
"_csrf": doc.GetCSRF(),
|
||||
"origin": doc.GetInputValueByName("origin"),
|
||||
"latest_commit_id": firstCommitID,
|
||||
|
@ -846,77 +865,166 @@ func TestPullRequestStaleReview(t *testing.T) {
|
|||
"type": "comment",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
// Review is not stale.
|
||||
review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID})
|
||||
assert.False(t, review.Stale)
|
||||
|
||||
// Create second commit
|
||||
require.NoError(t, os.WriteFile(path.Join(dstPath, "README.md"), []byte("## I prefer this heading"), 0o600))
|
||||
require.NoError(t, git.AddChanges(dstPath, true))
|
||||
require.NoError(t, git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||
Committer: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Author: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "user2",
|
||||
When: time.Now(),
|
||||
},
|
||||
Message: "Add README.",
|
||||
}))
|
||||
|
||||
// Push to agit PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// Review is stale.
|
||||
review = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID})
|
||||
assert.True(t, review.Stale)
|
||||
})
|
||||
|
||||
t.Run("Create stale review", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
staleReview := func(t *testing.T, firstCommitID string, index int64) {
|
||||
// Review based on the first commit, which is a stale review because the
|
||||
// PR's head is at the seconnd commit.
|
||||
req := NewRequestWithValues(t, "POST", "/"+repo.FullName()+"/pulls/1/files/reviews/submit", map[string]string{
|
||||
"_csrf": doc.GetCSRF(),
|
||||
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/pulls/%d/files/reviews/submit", repo.FullName(), index), map[string]string{
|
||||
"_csrf": GetCSRF(t, session, fmt.Sprintf("/%s/pulls/%d/files/reviews/new_comment", repo.FullName(), index)),
|
||||
"commit_id": firstCommitID,
|
||||
"content": "looks good",
|
||||
"type": "approve",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
// There does not exist a review that is not stale, because all reviews
|
||||
// are based on the first commit and the PR's head is at the second commit.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = false")
|
||||
t.Run("Across repositories", func(t *testing.T) {
|
||||
testRepoFork(t, session, "user2", repo.Name, "org3", "forked-repo")
|
||||
|
||||
// Clone it.
|
||||
dstPath := clone(t, fmt.Sprintf("%sorg3/forked-repo.git", u.String()))
|
||||
|
||||
// Create first commit.
|
||||
firstCommitID := firstCommit(t, dstPath)
|
||||
|
||||
// Create PR across repositories.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "main").Run(&git.RunOpts{Dir: dstPath}))
|
||||
session.MakeRequest(t, NewRequestWithValues(t, "POST", repo.FullName()+"/compare/main...org3/forked-repo:main", map[string]string{
|
||||
"_csrf": GetCSRF(t, session, repo.FullName()+"/compare/main...org3/forked-repo:main"),
|
||||
"title": "pull request",
|
||||
}), http.StatusOK)
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Index: 1, BaseRepoID: repo.ID})
|
||||
|
||||
t.Run("Mark review as stale", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Create first review
|
||||
firstReview(t, firstCommitID, pr.Index)
|
||||
|
||||
// Review is not stale.
|
||||
review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID})
|
||||
assert.False(t, review.Stale)
|
||||
|
||||
// Create second commit
|
||||
secondCommit(t, dstPath)
|
||||
|
||||
// Push to PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "main").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// Review is stale.
|
||||
assert.Eventually(t, func() bool {
|
||||
return unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID}).Stale == true
|
||||
}, time.Second*10, time.Microsecond*100)
|
||||
})
|
||||
|
||||
t.Run("Create stale review", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Review based on the first commit, which is a stale review because the
|
||||
// PR's head is at the seconnd commit.
|
||||
staleReview(t, firstCommitID, pr.Index)
|
||||
|
||||
// There does not exist a review that is not stale, because all reviews
|
||||
// are based on the first commit and the PR's head is at the second commit.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = false")
|
||||
})
|
||||
|
||||
t.Run("Mark unstale", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Force push the PR to the first commit.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "reset", "--hard", "HEAD~1").Run(&git.RunOpts{Dir: dstPath}))
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "--force-with-lease", "origin", "main").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// There does not exist a review that is stale, because all reviews
|
||||
// are based on the first commit and thus all reviews are no longer marked
|
||||
// as stale.
|
||||
assert.Eventually(t, func() bool {
|
||||
return !unittest.BeanExists(t, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
|
||||
}, time.Second*10, time.Microsecond*100)
|
||||
})
|
||||
|
||||
t.Run("Diff did not change", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Create a empty commit and push it to the PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "commit", "--allow-empty", "-m", "Empty commit").Run(&git.RunOpts{Dir: dstPath}))
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "main").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// There does not exist a review that is stale, because the diff did not
|
||||
// change.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Mark unstale", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
t.Run("AGit", func(t *testing.T) {
|
||||
dstPath := clone(t, fmt.Sprintf("%suser2/%s.git", u.String(), repo.Name))
|
||||
|
||||
// Force push the PR to the first commit.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "reset", "--hard", "HEAD~1").Run(&git.RunOpts{Dir: dstPath}))
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr", "-o", "force-push").Run(&git.RunOpts{Dir: dstPath}))
|
||||
// Create first commit.
|
||||
firstCommitID := firstCommit(t, dstPath)
|
||||
|
||||
// There does not exist a review that is stale, because all reviews
|
||||
// are based on the first commit and thus all reviews are no longer marked
|
||||
// as stale.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
|
||||
})
|
||||
|
||||
t.Run("Diff did not change", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Create a empty commit and push it to the PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "commit", "--allow-empty", "-m", "Empty commit").Run(&git.RunOpts{Dir: dstPath}))
|
||||
// Create agit PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// There does not exist a review that is stale, because the diff did not
|
||||
// change.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{Index: 2, BaseRepoID: repo.ID})
|
||||
|
||||
t.Run("Mark review as stale", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
firstReview(t, firstCommitID, pr.Index)
|
||||
|
||||
// Review is not stale.
|
||||
review := unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID})
|
||||
assert.False(t, review.Stale)
|
||||
|
||||
// Create second commit
|
||||
secondCommit(t, dstPath)
|
||||
|
||||
// Push to agit PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// Review is stale.
|
||||
review = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{IssueID: pr.IssueID})
|
||||
assert.True(t, review.Stale)
|
||||
})
|
||||
|
||||
t.Run("Create stale review", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Review based on the first commit, which is a stale review because the
|
||||
// PR's head is at the seconnd commit.
|
||||
staleReview(t, firstCommitID, pr.Index)
|
||||
|
||||
// There does not exist a review that is not stale, because all reviews
|
||||
// are based on the first commit and the PR's head is at the second commit.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = false")
|
||||
})
|
||||
|
||||
t.Run("Mark unstale", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Force push the PR to the first commit.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "reset", "--hard", "HEAD~1").Run(&git.RunOpts{Dir: dstPath}))
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr", "-o", "force-push").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// There does not exist a review that is stale, because all reviews
|
||||
// are based on the first commit and thus all reviews are no longer marked
|
||||
// as stale.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
|
||||
})
|
||||
|
||||
t.Run("Diff did not change", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Create a empty commit and push it to the PR.
|
||||
require.NoError(t, git.NewCommand(t.Context(), "commit", "--allow-empty", "-m", "Empty commit").Run(&git.RunOpts{Dir: dstPath}))
|
||||
require.NoError(t, git.NewCommand(t.Context(), "push", "origin", "HEAD:refs/for/main", "-o", "topic=agit-pr").Run(&git.RunOpts{Dir: dstPath}))
|
||||
|
||||
// There does not exist a review that is stale, because the diff did not
|
||||
// change.
|
||||
unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID}, "stale = true")
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
24
web_src/fomantic/package-lock.json
generated
24
web_src/fomantic/package-lock.json
generated
|
@ -132,9 +132,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.2.tgz",
|
||||
"integrity": "sha512-ODsoD39Lq6vR6aBgvjTnA3nZGliknKboc9Gtxr7E4WDNqY24MxANKcuDQSF0jzapvGb3KWOEDrKfve4HoWGK+g==",
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.3.tgz",
|
||||
"integrity": "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
@ -494,9 +494,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.10.tgz",
|
||||
"integrity": "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==",
|
||||
"version": "24.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.13.tgz",
|
||||
"integrity": "sha512-Qm9OYVOFHFYg3wJoTSrz80hoec5Lia/dPp84do3X7dZvLikQvM1YpmvTBEdIr/e+U8HTkFjLHLnl78K/qjf+jQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.8.0"
|
||||
|
@ -2005,9 +2005,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": {
|
||||
|
@ -5850,9 +5850,9 @@
|
|||
"license": "ISC"
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.22.2",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz",
|
||||
"integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==",
|
||||
"version": "2.23.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz",
|
||||
"integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
|
|
|
@ -226,7 +226,7 @@ export async function initDropzone(dropzoneEl, zone = undefined) {
|
|||
inputPath.name = `files_fullpath[${data.uuid}]`;
|
||||
inputPath.type = 'hidden';
|
||||
inputPath.value = htmlEscape(file.fullPath || file.name);
|
||||
dropzoneEl.querySelector('.files').append(input).append(inputPath);
|
||||
dropzoneEl.querySelector('.files').append(input, inputPath);
|
||||
|
||||
// Create a "Copy Link" element, to conveniently copy the image
|
||||
// or file link as Markdown to the clipboard
|
||||
|
|
|
@ -11,8 +11,6 @@ import {initTextExpander} from './TextExpander.js';
|
|||
import {showErrorToast, showHintToast} from '../../modules/toast.js';
|
||||
import {POST} from '../../modules/fetch.js';
|
||||
|
||||
let elementIdCounter = 0;
|
||||
|
||||
/**
|
||||
* validate if the given textarea is non-empty.
|
||||
* @param {HTMLElement} textarea - The textarea element to be validated.
|
||||
|
@ -39,10 +37,13 @@ export function validateTextareaNonEmpty(textarea) {
|
|||
const listPrefixRegex = /^\s*((\d+)[.)]\s|[-*+]\s{1,4}\[[ x]\]\s?|[-*+]\s|(>\s?)+)?/;
|
||||
|
||||
class ComboMarkdownEditor {
|
||||
static idSuffixCounter = 0;
|
||||
|
||||
constructor(container, options = {}) {
|
||||
container._giteaComboMarkdownEditor = this;
|
||||
this.options = options;
|
||||
this.container = container;
|
||||
this.elementIdSuffix = ComboMarkdownEditor.idSuffixCounter++;
|
||||
}
|
||||
|
||||
async init() {
|
||||
|
@ -55,8 +56,6 @@ class ComboMarkdownEditor {
|
|||
this.setupLinkInserter();
|
||||
|
||||
await this.switchToUserPreference();
|
||||
|
||||
elementIdCounter++;
|
||||
}
|
||||
|
||||
applyEditorHeights(el, heights) {
|
||||
|
@ -74,7 +73,7 @@ class ComboMarkdownEditor {
|
|||
setupTextarea() {
|
||||
this.textarea = this.container.querySelector('.markdown-text-editor');
|
||||
this.textarea._giteaComboMarkdownEditor = this;
|
||||
this.textarea.id = `_combo_markdown_editor_${elementIdCounter}`;
|
||||
this.textarea.id = `_combo_markdown_editor_${this.elementIdSuffix}`;
|
||||
this.textarea.addEventListener('input', (e) => this.options?.onContentChanged?.(this, e));
|
||||
this.applyEditorHeights(this.textarea, this.options.editorHeights);
|
||||
|
||||
|
@ -96,8 +95,8 @@ class ComboMarkdownEditor {
|
|||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="unindent"]')?.addEventListener('click', () => {
|
||||
this.indentSelection(true, false);
|
||||
});
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-table"]')?.setAttribute('data-modal', `div[data-markdown-table-modal-id="${elementIdCounter}"]`);
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-link"]')?.setAttribute('data-modal', `div[data-markdown-link-modal-id="${elementIdCounter}"]`);
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-table"]')?.setAttribute('data-modal', `div[data-markdown-table-modal-id="${this.elementIdSuffix}"]`);
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-link"]')?.setAttribute('data-modal', `div[data-markdown-link-modal-id="${this.elementIdSuffix}"]`);
|
||||
|
||||
// Track whether any actual input or pointer action was made after focusing, and only intercept Tab presses after that.
|
||||
this.tabEnabled = false;
|
||||
|
@ -195,7 +194,7 @@ class ComboMarkdownEditor {
|
|||
setupDropzone() {
|
||||
const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container');
|
||||
if (dropzoneParentContainer) {
|
||||
this.dropzone = this.container.closest(this.container.getAttribute('data-dropzone-parent-container'))?.querySelector('.dropzone');
|
||||
this.dropzone = this.container.closest(dropzoneParentContainer)?.querySelector('.dropzone');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,13 +206,13 @@ class ComboMarkdownEditor {
|
|||
// So here it uses our defined "data-tab-for" and "data-tab-panel" to generate the "data-tab" attribute for Fomantic.
|
||||
const tabEditor = Array.from(tabs).find((tab) => tab.getAttribute('data-tab-for') === 'markdown-writer');
|
||||
const tabPreviewer = Array.from(tabs).find((tab) => tab.getAttribute('data-tab-for') === 'markdown-previewer');
|
||||
tabEditor.setAttribute('data-tab', `markdown-writer-${elementIdCounter}`);
|
||||
tabPreviewer.setAttribute('data-tab', `markdown-previewer-${elementIdCounter}`);
|
||||
tabEditor.setAttribute('data-tab', `markdown-writer-${this.elementIdSuffix}`);
|
||||
tabPreviewer.setAttribute('data-tab', `markdown-previewer-${this.elementIdSuffix}`);
|
||||
const toolbar = $container[0].querySelector('markdown-toolbar');
|
||||
const panelEditor = $container[0].querySelector('.ui.tab[data-tab-panel="markdown-writer"]');
|
||||
const panelPreviewer = $container[0].querySelector('.ui.tab[data-tab-panel="markdown-previewer"]');
|
||||
panelEditor.setAttribute('data-tab', `markdown-writer-${elementIdCounter}`);
|
||||
panelPreviewer.setAttribute('data-tab', `markdown-previewer-${elementIdCounter}`);
|
||||
panelEditor.setAttribute('data-tab', `markdown-writer-${this.elementIdSuffix}`);
|
||||
panelPreviewer.setAttribute('data-tab', `markdown-previewer-${this.elementIdSuffix}`);
|
||||
|
||||
tabEditor.addEventListener('click', () => {
|
||||
toolbar.classList.remove('markdown-toolbar-hidden');
|
||||
|
@ -276,10 +275,10 @@ class ComboMarkdownEditor {
|
|||
|
||||
setupTableInserter() {
|
||||
const newTableModal = this.container.querySelector('div[data-modal-name="new-markdown-table"]');
|
||||
newTableModal.setAttribute('data-markdown-table-modal-id', elementIdCounter);
|
||||
newTableModal.setAttribute('data-markdown-table-modal-id', this.elementIdSuffix);
|
||||
|
||||
const button = newTableModal.querySelector('button[data-selector-name="ok-button"]');
|
||||
button.setAttribute('data-element-id', elementIdCounter);
|
||||
button.setAttribute('data-element-id', this.elementIdSuffix);
|
||||
button.addEventListener('click', this.addNewTable);
|
||||
}
|
||||
|
||||
|
@ -311,8 +310,8 @@ class ComboMarkdownEditor {
|
|||
|
||||
setupLinkInserter() {
|
||||
const newLinkModal = this.container.querySelector('div[data-modal-name="new-markdown-link"]');
|
||||
newLinkModal.setAttribute('data-markdown-link-modal-id', elementIdCounter);
|
||||
const textarea = document.getElementById(`_combo_markdown_editor_${elementIdCounter}`);
|
||||
newLinkModal.setAttribute('data-markdown-link-modal-id', this.elementIdSuffix);
|
||||
const textarea = document.getElementById(`_combo_markdown_editor_${this.elementIdSuffix}`);
|
||||
|
||||
$(newLinkModal).modal({
|
||||
// Pre-fill the description field from the selection to create behavior similar
|
||||
|
@ -331,7 +330,7 @@ class ComboMarkdownEditor {
|
|||
});
|
||||
|
||||
const button = newLinkModal.querySelector('button[data-selector-name="ok-button"]');
|
||||
button.setAttribute('data-element-id', elementIdCounter);
|
||||
button.setAttribute('data-element-id', this.elementIdSuffix);
|
||||
button.addEventListener('click', this.addNewLink);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue