Skip to content

Commit aaa61c4

Browse files
authored
Merge branch 'main' into expandertypes2
2 parents b020821 + 5a7b42d commit aaa61c4

File tree

29 files changed

+303
-225
lines changed

29 files changed

+303
-225
lines changed

models/fixtures/repository.yml

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,19 +1694,6 @@
16941694
is_fsck_enabled: true
16951695
close_issues_via_commit_in_any_branch: false
16961696

1697-
-
1698-
id: 59
1699-
owner_id: 2
1700-
owner_name: user2
1701-
lower_name: test_commit_revert
1702-
name: test_commit_revert
1703-
default_branch: main
1704-
is_empty: false
1705-
is_archived: false
1706-
is_private: true
1707-
status: 0
1708-
num_issues: 0
1709-
17101697
-
17111698
id: 60
17121699
owner_id: 40

models/fixtures/user.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
num_followers: 2
6868
num_following: 1
6969
num_stars: 2
70-
num_repos: 15
70+
num_repos: 14
7171
num_teams: 0
7272
num_members: 0
7373
visibility: 0

routers/web/repo/branch.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func Branches(ctx *context.Context) {
9393

9494
// DeleteBranchPost responses for delete merged branch
9595
func DeleteBranchPost(ctx *context.Context) {
96-
defer redirect(ctx)
96+
defer jsonRedirectBranches(ctx)
9797
branchName := ctx.FormString("name")
9898

9999
if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName, nil); err != nil {
@@ -120,7 +120,7 @@ func DeleteBranchPost(ctx *context.Context) {
120120

121121
// RestoreBranchPost responses for delete merged branch
122122
func RestoreBranchPost(ctx *context.Context) {
123-
defer redirect(ctx)
123+
defer jsonRedirectBranches(ctx)
124124

125125
branchID := ctx.FormInt64("branch_id")
126126
branchName := ctx.FormString("name")
@@ -170,7 +170,7 @@ func RestoreBranchPost(ctx *context.Context) {
170170
ctx.Flash.Success(ctx.Tr("repo.branch.restore_success", deletedBranch.Name))
171171
}
172172

173-
func redirect(ctx *context.Context) {
173+
func jsonRedirectBranches(ctx *context.Context) {
174174
ctx.JSONRedirect(ctx.Repo.RepoLink + "/branches?page=" + url.QueryEscape(ctx.FormString("page")))
175175
}
176176

routers/web/repo/cherry_pick.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,19 @@ func CherryPickPost(ctx *context.Context) {
114114
message += "\n\n" + form.CommitMessage
115115
}
116116

117+
gitCommitter, valid := WebGitOperationGetCommitChosenEmailIdentity(ctx, form.CommitEmail)
118+
if !valid {
119+
ctx.Data["Err_CommitEmail"] = true
120+
ctx.RenderWithErr(ctx.Tr("repo.editor.invalid_commit_email"), tplCherryPick, &form)
121+
return
122+
}
117123
opts := &files.ApplyDiffPatchOptions{
118124
LastCommitID: form.LastCommit,
119125
OldBranch: ctx.Repo.BranchName,
120126
NewBranch: branchName,
121127
Message: message,
128+
Author: gitCommitter,
129+
Committer: gitCommitter,
122130
}
123131

124132
// First lets try the simple plain read-tree -m approach

routers/web/repo/editor.go

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
git_model "code.gitea.io/gitea/models/git"
1414
repo_model "code.gitea.io/gitea/models/repo"
1515
"code.gitea.io/gitea/models/unit"
16-
user_model "code.gitea.io/gitea/models/user"
1716
"code.gitea.io/gitea/modules/charset"
1817
"code.gitea.io/gitea/modules/git"
1918
"code.gitea.io/gitea/modules/json"
@@ -103,18 +102,6 @@ func getParentTreeFields(treePath string) (treeNames, treePaths []string) {
103102
return treeNames, treePaths
104103
}
105104

106-
func getCandidateEmailAddresses(ctx *context.Context) []string {
107-
emails, err := user_model.GetActivatedEmailAddresses(ctx, ctx.Doer.ID)
108-
if err != nil {
109-
log.Error("getCandidateEmailAddresses: GetActivatedEmailAddresses: %v", err)
110-
}
111-
112-
if ctx.Doer.KeepEmailPrivate {
113-
emails = append([]string{ctx.Doer.GetPlaceholderEmail()}, emails...)
114-
}
115-
return emails
116-
}
117-
118105
func editFileCommon(ctx *context.Context, isNewFile bool) {
119106
ctx.Data["PageIsEdit"] = true
120107
ctx.Data["IsNewFile"] = isNewFile
@@ -123,8 +110,6 @@ func editFileCommon(ctx *context.Context, isNewFile bool) {
123110
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
124111
ctx.Data["IsEditingFileOnly"] = ctx.FormString("return_uri") != ""
125112
ctx.Data["ReturnURI"] = ctx.FormString("return_uri")
126-
ctx.Data["CommitCandidateEmails"] = getCandidateEmailAddresses(ctx)
127-
ctx.Data["CommitDefaultEmail"] = ctx.Doer.GetEmail()
128113
}
129114

130115
func editFile(ctx *context.Context, isNewFile bool) {
@@ -287,15 +272,11 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
287272
message += "\n\n" + form.CommitMessage
288273
}
289274

290-
gitCommitter := &files_service.IdentityOptions{}
291-
if form.CommitEmail != "" {
292-
if util.SliceContainsString(getCandidateEmailAddresses(ctx), form.CommitEmail, true) {
293-
gitCommitter.GitUserEmail = form.CommitEmail
294-
} else {
295-
ctx.Data["Err_CommitEmail"] = true
296-
ctx.RenderWithErr(ctx.Tr("repo.editor.invalid_commit_email"), tplEditFile, &form)
297-
return
298-
}
275+
gitCommitter, valid := WebGitOperationGetCommitChosenEmailIdentity(ctx, form.CommitEmail)
276+
if !valid {
277+
ctx.Data["Err_CommitEmail"] = true
278+
ctx.RenderWithErr(ctx.Tr("repo.editor.invalid_commit_email"), tplEditFile, &form)
279+
return
299280
}
300281

301282
operation := "update"
@@ -515,6 +496,13 @@ func DeleteFilePost(ctx *context.Context) {
515496
message += "\n\n" + form.CommitMessage
516497
}
517498

499+
gitCommitter, valid := WebGitOperationGetCommitChosenEmailIdentity(ctx, form.CommitEmail)
500+
if !valid {
501+
ctx.Data["Err_CommitEmail"] = true
502+
ctx.RenderWithErr(ctx.Tr("repo.editor.invalid_commit_email"), tplDeleteFile, &form)
503+
return
504+
}
505+
518506
if _, err := files_service.ChangeRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.ChangeRepoFilesOptions{
519507
LastCommitID: form.LastCommit,
520508
OldBranch: ctx.Repo.BranchName,
@@ -525,8 +513,10 @@ func DeleteFilePost(ctx *context.Context) {
525513
TreePath: ctx.Repo.TreePath,
526514
},
527515
},
528-
Message: message,
529-
Signoff: form.Signoff,
516+
Message: message,
517+
Signoff: form.Signoff,
518+
Author: gitCommitter,
519+
Committer: gitCommitter,
530520
}); err != nil {
531521
// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
532522
if git.IsErrNotExist(err) || files_service.IsErrRepoFileDoesNotExist(err) {
@@ -726,6 +716,13 @@ func UploadFilePost(ctx *context.Context) {
726716
message += "\n\n" + form.CommitMessage
727717
}
728718

719+
gitCommitter, valid := WebGitOperationGetCommitChosenEmailIdentity(ctx, form.CommitEmail)
720+
if !valid {
721+
ctx.Data["Err_CommitEmail"] = true
722+
ctx.RenderWithErr(ctx.Tr("repo.editor.invalid_commit_email"), tplUploadFile, &form)
723+
return
724+
}
725+
729726
if err := files_service.UploadRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.UploadRepoFileOptions{
730727
LastCommitID: ctx.Repo.CommitID,
731728
OldBranch: oldBranchName,
@@ -734,6 +731,8 @@ func UploadFilePost(ctx *context.Context) {
734731
Message: message,
735732
Files: form.Files,
736733
Signoff: form.Signoff,
734+
Author: gitCommitter,
735+
Committer: gitCommitter,
737736
}); err != nil {
738737
if git_model.IsErrLFSFileLocked(err) {
739738
ctx.Data["Err_TreePath"] = true

routers/web/repo/patch.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func NewDiffPatchPost(ctx *context.Context) {
6666
return
6767
}
6868

69-
// Cannot commit to a an existing branch if user doesn't have rights
69+
// Cannot commit to an existing branch if user doesn't have rights
7070
if branchName == ctx.Repo.BranchName && !canCommit {
7171
ctx.Data["Err_NewBranchName"] = true
7272
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
@@ -86,12 +86,21 @@ func NewDiffPatchPost(ctx *context.Context) {
8686
message += "\n\n" + form.CommitMessage
8787
}
8888

89+
gitCommitter, valid := WebGitOperationGetCommitChosenEmailIdentity(ctx, form.CommitEmail)
90+
if !valid {
91+
ctx.Data["Err_CommitEmail"] = true
92+
ctx.RenderWithErr(ctx.Tr("repo.editor.invalid_commit_email"), tplPatchFile, &form)
93+
return
94+
}
95+
8996
fileResponse, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, &files.ApplyDiffPatchOptions{
9097
LastCommitID: form.LastCommit,
9198
OldBranch: ctx.Repo.BranchName,
9299
NewBranch: branchName,
93100
Message: message,
94101
Content: strings.ReplaceAll(form.Content, "\r", ""),
102+
Author: gitCommitter,
103+
Committer: gitCommitter,
95104
})
96105
if err != nil {
97106
if git_model.IsErrBranchAlreadyExists(err) {

routers/web/repo/view_home.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,19 @@ func Home(ctx *context.Context) {
413413
ctx.HTML(http.StatusOK, tplRepoHome)
414414
}
415415

416-
// HomeRedirect redirects from /tree/* to /src/* in order to maintain a similar URL structure.
417-
func HomeRedirect(ctx *context.Context) {
418-
remainder := ctx.PathParam("*")
419-
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + util.PathEscapeSegments(remainder))
416+
func RedirectRepoTreeToSrc(ctx *context.Context) {
417+
// Redirect "/owner/repo/tree/*" requests to "/owner/repo/src/*",
418+
// then use the deprecated "/src/*" handler to guess the ref type and render a file list page.
419+
// This is done intentionally so that Gitea's repo URL structure matches other forges (GitHub/GitLab) provide,
420+
// allowing us to construct submodule URLs across forges easily.
421+
// For example, when viewing a submodule, we can simply construct the link as:
422+
// * "https://gitea/owner/repo/tree/{CommitID}"
423+
// * "https://github/owner/repo/tree/{CommitID}"
424+
// * "https://gitlab/owner/repo/tree/{CommitID}"
425+
// Then no matter which forge the submodule is using, the link works.
426+
redirect := ctx.Repo.RepoLink + "/src/" + ctx.PathParamRaw("*")
427+
if ctx.Req.URL.RawQuery != "" {
428+
redirect += "?" + ctx.Req.URL.RawQuery
429+
}
430+
ctx.Redirect(redirect)
420431
}

routers/web/repo/webgit.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package repo
5+
6+
import (
7+
user_model "code.gitea.io/gitea/models/user"
8+
"code.gitea.io/gitea/modules/log"
9+
"code.gitea.io/gitea/modules/setting"
10+
"code.gitea.io/gitea/modules/util"
11+
"code.gitea.io/gitea/services/context"
12+
files_service "code.gitea.io/gitea/services/repository/files"
13+
)
14+
15+
func WebGitOperationCommonData(ctx *context.Context) {
16+
// TODO: more places like "wiki page" and "merging a pull request or creating an auto merge merging task"
17+
emails, err := user_model.GetActivatedEmailAddresses(ctx, ctx.Doer.ID)
18+
if err != nil {
19+
log.Error("WebGitOperationCommonData: GetActivatedEmailAddresses: %v", err)
20+
}
21+
if ctx.Doer.KeepEmailPrivate {
22+
emails = append([]string{ctx.Doer.GetPlaceholderEmail()}, emails...)
23+
}
24+
ctx.Data["CommitCandidateEmails"] = emails
25+
ctx.Data["CommitDefaultEmail"] = ctx.Doer.GetEmail()
26+
}
27+
28+
func WebGitOperationGetCommitChosenEmailIdentity(ctx *context.Context, email string) (_ *files_service.IdentityOptions, valid bool) {
29+
if ctx.Data["CommitCandidateEmails"] == nil {
30+
setting.PanicInDevOrTesting("no CommitCandidateEmails in context data")
31+
}
32+
emails, _ := ctx.Data["CommitCandidateEmails"].([]string)
33+
if email == "" {
34+
return nil, true
35+
}
36+
if util.SliceContainsString(emails, email, true) {
37+
return &files_service.IdentityOptions{GitUserEmail: email}, true
38+
}
39+
return nil, false
40+
}

routers/web/web.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,21 +1294,20 @@ func registerRoutes(m *web.Router) {
12941294
m.Group("/{username}/{reponame}", func() { // repo code
12951295
m.Group("", func() {
12961296
m.Group("", func() {
1297+
m.Post("/_preview/*", web.Bind(forms.EditPreviewDiffForm{}), repo.DiffPreviewPost)
12971298
m.Combo("/_edit/*").Get(repo.EditFile).
12981299
Post(web.Bind(forms.EditRepoFileForm{}), repo.EditFilePost)
12991300
m.Combo("/_new/*").Get(repo.NewFile).
13001301
Post(web.Bind(forms.EditRepoFileForm{}), repo.NewFilePost)
1301-
m.Post("/_preview/*", web.Bind(forms.EditPreviewDiffForm{}), repo.DiffPreviewPost)
13021302
m.Combo("/_delete/*").Get(repo.DeleteFile).
13031303
Post(web.Bind(forms.DeleteRepoFileForm{}), repo.DeleteFilePost)
1304-
m.Combo("/_upload/*", repo.MustBeAbleToUpload).
1305-
Get(repo.UploadFile).
1304+
m.Combo("/_upload/*", repo.MustBeAbleToUpload).Get(repo.UploadFile).
13061305
Post(web.Bind(forms.UploadRepoFileForm{}), repo.UploadFilePost)
13071306
m.Combo("/_diffpatch/*").Get(repo.NewDiffPatch).
13081307
Post(web.Bind(forms.EditRepoFileForm{}), repo.NewDiffPatchPost)
13091308
m.Combo("/_cherrypick/{sha:([a-f0-9]{7,64})}/*").Get(repo.CherryPick).
13101309
Post(web.Bind(forms.CherryPickForm{}), repo.CherryPickPost)
1311-
}, context.RepoRefByType(git.RefTypeBranch), context.CanWriteToBranch())
1310+
}, context.RepoRefByType(git.RefTypeBranch), context.CanWriteToBranch(), repo.WebGitOperationCommonData)
13121311
m.Group("", func() {
13131312
m.Post("/upload-file", repo.UploadFileToServer)
13141313
m.Post("/upload-remove", web.Bind(forms.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
@@ -1583,13 +1582,7 @@ func registerRoutes(m *web.Router) {
15831582
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.Home)
15841583
m.Get("/*", context.RepoRefByType(""), repo.Home) // "/*" route is deprecated, and kept for backward compatibility
15851584
}, repo.SetEditorconfigIfExists)
1586-
1587-
// Add a /tree/* path to redirect to the /src/* path, which
1588-
// will redirect to the canonical URL for that ref. This is
1589-
// included so that Gitea's repo URL structure matches what
1590-
// other forges provide, allowing clients to construct URLs
1591-
// that work across forges.
1592-
m.Get("/tree/*", repo.HomeRedirect)
1585+
m.Get("/tree/*", repo.RedirectRepoTreeToSrc) // redirect "/owner/repo/tree/*" requests to "/owner/repo/src/*"
15931586

15941587
m.Get("/forks", context.RepoRef(), repo.Forks)
15951588
m.Get("/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}", repo.MustBeNotEmpty, repo.RawDiff)

services/context/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
293293
return
294294
}
295295

296-
refName, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.PathParam("*"), ctx.FormTrim("ref"))
296+
refName, _, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.PathParam("*"), ctx.FormTrim("ref"))
297297
var err error
298298

299299
if ctx.Repo.GitRepo.IsBranchExist(refName) {

0 commit comments

Comments
 (0)