mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-25 07:45:25 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
@@ -966,7 +966,7 @@ func SignInOAuthCallback(ctx *context.Context) {
|
||||
}
|
||||
|
||||
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
||||
IsActive: util.OptionalBoolOf(!setting.OAuth2Client.RegisterEmailConfirm),
|
||||
IsActive: util.OptionalBoolOf(!setting.OAuth2Client.RegisterEmailConfirm && !setting.Service.RegisterManualConfirm),
|
||||
}
|
||||
|
||||
source := authSource.Cfg.(*oauth2.Source)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package feed
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
// ShowBranchFeed shows tags and/or releases on the repo as RSS / Atom feed
|
||||
func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType string) {
|
||||
commits, err := ctx.Repo.Commit.CommitsByRange(0, 10)
|
||||
if err != nil {
|
||||
ctx.ServerError("ShowBranchFeed", err)
|
||||
return
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("Latest commits for branch %s", ctx.Repo.BranchName)
|
||||
link := &feeds.Link{Href: repo.HTMLURL() + "/" + ctx.Repo.BranchNameSubURL()}
|
||||
|
||||
feed := &feeds.Feed{
|
||||
Title: title,
|
||||
Link: link,
|
||||
Description: repo.Description,
|
||||
Created: time.Now(),
|
||||
}
|
||||
|
||||
for _, commit := range commits {
|
||||
feed.Items = append(feed.Items, &feeds.Item{
|
||||
Id: commit.ID.String(),
|
||||
Title: strings.TrimSpace(strings.Split(commit.Message(), "\n")[0]),
|
||||
Link: &feeds.Link{Href: repo.HTMLURL() + "/commit/" + commit.ID.String()},
|
||||
Author: &feeds.Author{
|
||||
Name: commit.Author.Name,
|
||||
Email: commit.Author.Email,
|
||||
},
|
||||
Description: commit.Message(),
|
||||
Content: commit.Message(),
|
||||
})
|
||||
}
|
||||
|
||||
writeFeed(ctx, feed, formatType)
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package feed
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
// ShowFileFeed shows tags and/or releases on the repo as RSS / Atom feed
|
||||
func ShowFileFeed(ctx *context.Context, repo *repo.Repository, formatType string) {
|
||||
fileName := ctx.Repo.TreePath
|
||||
if len(fileName) == 0 {
|
||||
return
|
||||
}
|
||||
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(ctx.Repo.RefName, fileName, 1)
|
||||
if err != nil {
|
||||
ctx.ServerError("ShowBranchFeed", err)
|
||||
return
|
||||
}
|
||||
|
||||
title := fmt.Sprintf("Latest commits for file %s", ctx.Repo.TreePath)
|
||||
|
||||
link := &feeds.Link{Href: repo.HTMLURL() + "/" + ctx.Repo.BranchNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)}
|
||||
|
||||
feed := &feeds.Feed{
|
||||
Title: title,
|
||||
Link: link,
|
||||
Description: repo.Description,
|
||||
Created: time.Now(),
|
||||
}
|
||||
|
||||
for _, commit := range commits {
|
||||
feed.Items = append(feed.Items, &feeds.Item{
|
||||
Id: commit.ID.String(),
|
||||
Title: strings.TrimSpace(strings.Split(commit.Message(), "\n")[0]),
|
||||
Link: &feeds.Link{Href: repo.HTMLURL() + "/commit/" + commit.ID.String()},
|
||||
Author: &feeds.Author{
|
||||
Name: commit.Author.Name,
|
||||
Email: commit.Author.Email,
|
||||
},
|
||||
Description: commit.Message(),
|
||||
Content: commit.Message(),
|
||||
})
|
||||
}
|
||||
|
||||
writeFeed(ctx, feed, formatType)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package feed
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
)
|
||||
|
||||
// RenderBranchFeed render format for branch or file
|
||||
func RenderBranchFeed(ctx *context.Context) {
|
||||
_, _, showFeedType := GetFeedType(ctx.Params(":reponame"), ctx.Req)
|
||||
if ctx.Repo.TreePath == "" {
|
||||
ShowBranchFeed(ctx, ctx.Repo.Repository, showFeedType)
|
||||
} else {
|
||||
ShowFileFeed(ctx, ctx.Repo.Repository, showFeedType)
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,6 @@ func Home(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Owner"] = org
|
||||
ctx.Data["Repos"] = repos
|
||||
ctx.Data["Total"] = count
|
||||
ctx.Data["MembersTotal"] = membersCount
|
||||
|
||||
@@ -62,6 +62,7 @@ func Members(ctx *context.Context) {
|
||||
}
|
||||
ctx.Data["Page"] = pager
|
||||
ctx.Data["Members"] = members
|
||||
ctx.Data["ContextUser"] = ctx.ContextUser
|
||||
ctx.Data["MembersIsPublicMember"] = membersIsPublic
|
||||
ctx.Data["MembersIsUserOrgOwner"] = organization.IsUserOrgOwner(members, org.ID)
|
||||
ctx.Data["MembersTwoFaStatus"] = members.GetTwoFaStatus()
|
||||
|
||||
@@ -610,6 +610,23 @@ func SetDefaultProjectBoard(ctx *context.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// UnsetDefaultProjectBoard unset default board for uncategorized issues/pulls
|
||||
func UnsetDefaultProjectBoard(ctx *context.Context) {
|
||||
project, _ := CheckProjectBoardChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.SetDefaultBoard(project.ID, 0); err != nil {
|
||||
ctx.ServerError("SetDefaultBoard", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"ok": true,
|
||||
})
|
||||
}
|
||||
|
||||
// MoveIssues moves or keeps issues in a column and sorts them inside that column
|
||||
func MoveIssues(ctx *context.Context) {
|
||||
if ctx.Doer == nil {
|
||||
|
||||
@@ -43,6 +43,8 @@ func SecretsPost(ctx *context.Context) {
|
||||
func SecretsDelete(ctx *context.Context) {
|
||||
shared.PerformSecretsDelete(
|
||||
ctx,
|
||||
ctx.ContextUser.ID,
|
||||
0,
|
||||
ctx.Org.OrgLink+"/settings/secrets",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ func Teams(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
ctx.Data["Teams"] = ctx.Org.Teams
|
||||
ctx.Data["ContextUser"] = ctx.ContextUser
|
||||
|
||||
ctx.HTML(http.StatusOK, tplTeams)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package actions
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
@@ -11,11 +12,14 @@ import (
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
|
||||
"github.com/nektos/act/pkg/model"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -24,9 +28,8 @@ const (
|
||||
)
|
||||
|
||||
type Workflow struct {
|
||||
Entry git.TreeEntry
|
||||
IsInvalid bool
|
||||
ErrMsg string
|
||||
Entry git.TreeEntry
|
||||
ErrMsg string
|
||||
}
|
||||
|
||||
// MustEnableActions check if actions are enabled in settings
|
||||
@@ -73,6 +76,23 @@ func List(ctx *context.Context) {
|
||||
ctx.Error(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Get all runner labels
|
||||
opts := actions_model.FindRunnerOptions{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
WithAvailable: true,
|
||||
}
|
||||
runners, err := actions_model.FindRunners(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.ServerError("FindRunners", err)
|
||||
return
|
||||
}
|
||||
allRunnerLabels := make(container.Set[string])
|
||||
for _, r := range runners {
|
||||
allRunnerLabels.AddMultiple(r.AgentLabels...)
|
||||
allRunnerLabels.AddMultiple(r.CustomLabels...)
|
||||
}
|
||||
|
||||
workflows = make([]Workflow, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
workflow := Workflow{Entry: *entry}
|
||||
@@ -81,10 +101,24 @@ func List(ctx *context.Context) {
|
||||
ctx.Error(http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
_, err = actions.GetEventsFromContent(content)
|
||||
wf, err := model.ReadWorkflow(bytes.NewReader(content))
|
||||
if err != nil {
|
||||
workflow.IsInvalid = true
|
||||
workflow.ErrMsg = err.Error()
|
||||
workflow.ErrMsg = ctx.Locale.Tr("actions.runs.invalid_workflow_helper", err.Error())
|
||||
workflows = append(workflows, workflow)
|
||||
continue
|
||||
}
|
||||
// Check whether have matching runner
|
||||
for _, j := range wf.Jobs {
|
||||
runsOnList := j.RunsOn()
|
||||
for _, ro := range runsOnList {
|
||||
if !allRunnerLabels.Contains(ro) {
|
||||
workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_runner_helper", ro)
|
||||
break
|
||||
}
|
||||
}
|
||||
if workflow.ErrMsg != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
workflows = append(workflows, workflow)
|
||||
}
|
||||
@@ -128,12 +162,18 @@ func List(ctx *context.Context) {
|
||||
ctx.Data["NumClosedActionRuns"] = numClosedRuns
|
||||
|
||||
opts.IsClosed = util.OptionalBoolNone
|
||||
if ctx.FormString("state") == "closed" {
|
||||
isShowClosed := ctx.FormString("state") == "closed"
|
||||
if len(ctx.FormString("state")) == 0 && numOpenRuns == 0 && numClosedRuns != 0 {
|
||||
isShowClosed = true
|
||||
}
|
||||
|
||||
if isShowClosed {
|
||||
opts.IsClosed = util.OptionalBoolTrue
|
||||
ctx.Data["IsShowClosed"] = true
|
||||
} else {
|
||||
opts.IsClosed = util.OptionalBoolFalse
|
||||
}
|
||||
|
||||
runs, total, err := actions_model.FindRuns(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, err.Error())
|
||||
|
||||
@@ -459,7 +459,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
||||
rootRepo.ID != ci.HeadRepo.ID &&
|
||||
rootRepo.ID != baseRepo.ID {
|
||||
canRead := access_model.CheckRepoUnitUser(ctx, rootRepo, ctx.Doer, unit.TypeCode)
|
||||
if canRead {
|
||||
if canRead && rootRepo.AllowsPulls() {
|
||||
ctx.Data["RootRepo"] = rootRepo
|
||||
if !fileOnly {
|
||||
branches, tags, err := getBranchesAndTagsForRepo(ctx, rootRepo)
|
||||
|
||||
+26
-18
@@ -82,7 +82,7 @@ func editFile(ctx *context.Context, isNewFile bool) {
|
||||
}
|
||||
|
||||
// Check if the filename (and additional path) is specified in the querystring
|
||||
// (filename is a misnomer, but kept for compatibility with Github)
|
||||
// (filename is a misnomer, but kept for compatibility with GitHub)
|
||||
filePath, fileName := path.Split(ctx.Req.URL.Query().Get("filename"))
|
||||
filePath = strings.Trim(filePath, "/")
|
||||
treeNames, treePaths := getParentTreeFields(path.Join(ctx.Repo.TreePath, filePath))
|
||||
@@ -327,6 +327,10 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Repo.Repository.IsEmpty {
|
||||
_ = repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, IsEmpty: false}, "is_empty")
|
||||
}
|
||||
|
||||
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
|
||||
} else {
|
||||
@@ -617,25 +621,25 @@ func UploadFilePost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var newTreePath string
|
||||
for _, part := range treeNames {
|
||||
newTreePath = path.Join(newTreePath, part)
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(newTreePath)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
// Means there is no item with that name, so we're good
|
||||
break
|
||||
if !ctx.Repo.Repository.IsEmpty {
|
||||
var newTreePath string
|
||||
for _, part := range treeNames {
|
||||
newTreePath = path.Join(newTreePath, part)
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(newTreePath)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
break // Means there is no item with that name, so we're good
|
||||
}
|
||||
ctx.ServerError("Repo.Commit.GetTreeEntryByPath", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.ServerError("Repo.Commit.GetTreeEntryByPath", err)
|
||||
return
|
||||
}
|
||||
|
||||
// User can only upload files to a directory.
|
||||
if !entry.IsDir() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), tplUploadFile, &form)
|
||||
return
|
||||
// User can only upload files to a directory, the directory name shouldn't be an existing file.
|
||||
if !entry.IsDir() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), tplUploadFile, &form)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,6 +718,10 @@ func UploadFilePost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.Repo.Repository.IsEmpty {
|
||||
_ = repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, IsEmpty: false}, "is_empty")
|
||||
}
|
||||
|
||||
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
|
||||
} else {
|
||||
|
||||
+21
-33
@@ -32,43 +32,31 @@ import (
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/go-chi/cors"
|
||||
)
|
||||
|
||||
func HTTPGitEnabledHandler(ctx *context.Context) {
|
||||
if setting.Repository.DisableHTTPGit {
|
||||
ctx.Resp.WriteHeader(http.StatusForbidden)
|
||||
_, _ = ctx.Resp.Write([]byte("Interacting with repositories by HTTP protocol is not allowed"))
|
||||
}
|
||||
}
|
||||
|
||||
func CorsHandler() func(next http.Handler) http.Handler {
|
||||
if setting.Repository.AccessControlAllowOrigin != "" {
|
||||
return cors.Handler(cors.Options{
|
||||
AllowedOrigins: []string{setting.Repository.AccessControlAllowOrigin},
|
||||
AllowedHeaders: []string{"Content-Type", "Authorization", "User-Agent"},
|
||||
})
|
||||
}
|
||||
return func(next http.Handler) http.Handler {
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
// httpBase implementation git smart HTTP protocol
|
||||
func httpBase(ctx *context.Context) (h *serviceHandler) {
|
||||
if setting.Repository.DisableHTTPGit {
|
||||
ctx.Resp.WriteHeader(http.StatusForbidden)
|
||||
_, err := ctx.Resp.Write([]byte("Interacting with repositories by HTTP protocol is not allowed"))
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(setting.Repository.AccessControlAllowOrigin) > 0 {
|
||||
allowedOrigin := setting.Repository.AccessControlAllowOrigin
|
||||
// Set CORS headers for browser-based git clients
|
||||
ctx.Resp.Header().Set("Access-Control-Allow-Origin", allowedOrigin)
|
||||
ctx.Resp.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, User-Agent")
|
||||
|
||||
// Handle preflight OPTIONS request
|
||||
if ctx.Req.Method == "OPTIONS" {
|
||||
if allowedOrigin == "*" {
|
||||
ctx.Status(http.StatusOK)
|
||||
} else if allowedOrigin == "null" {
|
||||
ctx.Status(http.StatusForbidden)
|
||||
} else {
|
||||
origin := ctx.Req.Header.Get("Origin")
|
||||
if len(origin) > 0 && origin == allowedOrigin {
|
||||
ctx.Status(http.StatusOK)
|
||||
} else {
|
||||
ctx.Status(http.StatusForbidden)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
username := ctx.Params(":username")
|
||||
reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
|
||||
|
||||
|
||||
+20
-14
@@ -1557,7 +1557,7 @@ func ViewIssue(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if comment.Type == issues_model.CommentTypeCode || comment.Type == issues_model.CommentTypeReview || comment.Type == issues_model.CommentTypeDismissReview {
|
||||
} else if comment.Type.HasContentSupport() {
|
||||
comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
|
||||
URLPrefix: ctx.Repo.RepoLink,
|
||||
Metas: ctx.Repo.Repository.ComposeMetas(),
|
||||
@@ -1621,8 +1621,10 @@ func ViewIssue(ctx *context.Context) {
|
||||
comment.Type == issues_model.CommentTypeStopTracking {
|
||||
// drop error since times could be pruned from DB..
|
||||
_ = comment.LoadTime()
|
||||
} else if comment.Type == issues_model.CommentTypeClose {
|
||||
// record ID of latest closed comment.
|
||||
}
|
||||
|
||||
if comment.Type == issues_model.CommentTypeClose || comment.Type == issues_model.CommentTypeMergePull {
|
||||
// record ID of the latest closed/merged comment.
|
||||
// if PR is closed, the comments whose type is CommentTypePullRequestPush(29) after latestCloseCommentID won't be rendered.
|
||||
latestCloseCommentID = comment.ID
|
||||
}
|
||||
@@ -2849,7 +2851,7 @@ func UpdateCommentContent(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeReview && comment.Type != issues_model.CommentTypeCode {
|
||||
if !comment.Type.HasContentSupport() {
|
||||
ctx.Error(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
@@ -2913,7 +2915,7 @@ func DeleteComment(ctx *context.Context) {
|
||||
if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
|
||||
ctx.Error(http.StatusForbidden)
|
||||
return
|
||||
} else if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeCode {
|
||||
} else if !comment.Type.HasContentSupport() {
|
||||
ctx.Error(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
@@ -3059,7 +3061,7 @@ func ChangeCommentReaction(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeCode && comment.Type != issues_model.CommentTypeReview {
|
||||
if !comment.Type.HasContentSupport() {
|
||||
ctx.Error(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
@@ -3175,15 +3177,19 @@ func GetCommentAttachments(ctx *context.Context) {
|
||||
ctx.NotFoundOrServerError("GetCommentByID", issues_model.IsErrCommentNotExist, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !comment.Type.HasAttachmentSupport() {
|
||||
ctx.ServerError("GetCommentAttachments", fmt.Errorf("comment type %v does not support attachments", comment.Type))
|
||||
return
|
||||
}
|
||||
|
||||
attachments := make([]*api.Attachment, 0)
|
||||
if comment.Type == issues_model.CommentTypeComment {
|
||||
if err := comment.LoadAttachments(ctx); err != nil {
|
||||
ctx.ServerError("LoadAttachments", err)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(comment.Attachments); i++ {
|
||||
attachments = append(attachments, convert.ToAttachment(comment.Attachments[i]))
|
||||
}
|
||||
if err := comment.LoadAttachments(ctx); err != nil {
|
||||
ctx.ServerError("LoadAttachments", err)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(comment.Attachments); i++ {
|
||||
attachments = append(attachments, convert.ToAttachment(comment.Attachments[i]))
|
||||
}
|
||||
ctx.JSON(http.StatusOK, attachments)
|
||||
}
|
||||
|
||||
@@ -576,6 +576,23 @@ func SetDefaultProjectBoard(ctx *context.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// UnSetDefaultProjectBoard unset default board for uncategorized issues/pulls
|
||||
func UnSetDefaultProjectBoard(ctx *context.Context) {
|
||||
project, _ := checkProjectBoardChangePermissions(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := project_model.SetDefaultBoard(project.ID, 0); err != nil {
|
||||
ctx.ServerError("SetDefaultBoard", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"ok": true,
|
||||
})
|
||||
}
|
||||
|
||||
// MoveIssues moves or keeps issues in a column and sorts them inside that column
|
||||
func MoveIssues(ctx *context.Context) {
|
||||
if ctx.Doer == nil {
|
||||
|
||||
+15
-20
@@ -29,21 +29,17 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
tplReleases base.TplName = "repo/release/list"
|
||||
tplReleaseNew base.TplName = "repo/release/new"
|
||||
tplReleasesList base.TplName = "repo/release/list"
|
||||
tplReleaseNew base.TplName = "repo/release/new"
|
||||
tplTagsList base.TplName = "repo/tag/list"
|
||||
)
|
||||
|
||||
// calReleaseNumCommitsBehind calculates given release has how many commits behind release target.
|
||||
func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *repo_model.Release, countCache map[string]int64) error {
|
||||
// Fast return if release target is same as default branch.
|
||||
if repoCtx.BranchName == release.Target {
|
||||
release.NumCommitsBehind = repoCtx.CommitsCount - release.NumCommits
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get count if not exists
|
||||
if _, ok := countCache[release.Target]; !ok {
|
||||
if repoCtx.GitRepo.IsBranchExist(release.Target) {
|
||||
// short-circuit for the default branch
|
||||
if repoCtx.Repository.DefaultBranch == release.Target || repoCtx.GitRepo.IsBranchExist(release.Target) {
|
||||
commit, err := repoCtx.GitRepo.GetBranchCommit(release.Target)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetBranchCommit: %w", err)
|
||||
@@ -63,16 +59,19 @@ func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *repo_model
|
||||
|
||||
// Releases render releases list page
|
||||
func Releases(ctx *context.Context) {
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.releases")
|
||||
releasesOrTags(ctx, false)
|
||||
}
|
||||
|
||||
// TagsList render tags list page
|
||||
func TagsList(ctx *context.Context) {
|
||||
ctx.Data["PageIsTagList"] = true
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.tags")
|
||||
releasesOrTags(ctx, true)
|
||||
}
|
||||
|
||||
func releasesOrTags(ctx *context.Context, isTagList bool) {
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch
|
||||
ctx.Data["IsViewBranch"] = false
|
||||
ctx.Data["IsViewTag"] = true
|
||||
@@ -80,14 +79,6 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
|
||||
ctx.Data["CanCreateBranch"] = false
|
||||
ctx.Data["HideBranchesInDropdown"] = true
|
||||
|
||||
if isTagList {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.tags")
|
||||
ctx.Data["PageIsTagList"] = true
|
||||
} else {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.releases")
|
||||
ctx.Data["PageIsTagList"] = false
|
||||
}
|
||||
|
||||
listOptions := db.ListOptions{
|
||||
Page: ctx.FormInt("page"),
|
||||
PageSize: ctx.FormInt("limit"),
|
||||
@@ -201,7 +192,11 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
|
||||
pager.SetDefaultParams(ctx)
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
ctx.HTML(http.StatusOK, tplReleases)
|
||||
if isTagList {
|
||||
ctx.HTML(http.StatusOK, tplTagsList)
|
||||
} else {
|
||||
ctx.HTML(http.StatusOK, tplReleasesList)
|
||||
}
|
||||
}
|
||||
|
||||
// ReleasesFeedRSS get feeds for releases in RSS format
|
||||
@@ -287,7 +282,7 @@ func SingleRelease(ctx *context.Context) {
|
||||
}
|
||||
|
||||
ctx.Data["Releases"] = []*repo_model.Release{release}
|
||||
ctx.HTML(http.StatusOK, tplReleases)
|
||||
ctx.HTML(http.StatusOK, tplReleasesList)
|
||||
}
|
||||
|
||||
// LatestRelease redirects to the latest release
|
||||
|
||||
@@ -41,6 +41,8 @@ func SecretsPost(ctx *context.Context) {
|
||||
func DeleteSecret(ctx *context.Context) {
|
||||
shared.PerformSecretsDelete(
|
||||
ctx,
|
||||
0,
|
||||
ctx.Repo.Repository.ID,
|
||||
ctx.Repo.RepoLink+"/settings/secrets",
|
||||
)
|
||||
}
|
||||
|
||||
+42
-23
@@ -24,6 +24,7 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
@@ -39,6 +40,8 @@ import (
|
||||
"code.gitea.io/gitea/modules/typesniffer"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/routers/web/feed"
|
||||
|
||||
"github.com/nektos/act/pkg/model"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -154,16 +157,6 @@ func renderDirectory(ctx *context.Context, treeLink string) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefName)
|
||||
}
|
||||
|
||||
// Check permission to add or upload new file.
|
||||
if ctx.Repo.CanWrite(unit_model.TypeCode) && ctx.Repo.IsViewBranch {
|
||||
ctx.Data["CanAddFile"] = !ctx.Repo.Repository.IsArchived
|
||||
ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived
|
||||
}
|
||||
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
subfolder, readmeFile, err := findReadmeFileInEntries(ctx, entries, true)
|
||||
if err != nil {
|
||||
ctx.ServerError("findReadmeFileInEntries", err)
|
||||
@@ -358,6 +351,15 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
|
||||
if issueConfigErr != nil {
|
||||
ctx.Data["FileError"] = strings.TrimSpace(issueConfigErr.Error())
|
||||
}
|
||||
} else if actions.IsWorkflow(ctx.Repo.TreePath) {
|
||||
content, err := actions.GetContentFromEntry(entry)
|
||||
if err != nil {
|
||||
log.Error("actions.GetContentFromEntry: %v", err)
|
||||
}
|
||||
_, workFlowErr := model.ReadWorkflow(bytes.NewReader(content))
|
||||
if workFlowErr != nil {
|
||||
ctx.Data["FileError"] = ctx.Locale.Tr("actions.runs.invalid_workflow_helper", workFlowErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
isDisplayingSource := ctx.FormString("display") == "source"
|
||||
@@ -705,10 +707,17 @@ func checkCitationFile(ctx *context.Context, entry *git.TreeEntry) {
|
||||
|
||||
// Home render repository home page
|
||||
func Home(ctx *context.Context) {
|
||||
if setting.EnableFeed {
|
||||
if setting.Other.EnableFeed {
|
||||
isFeed, _, showFeedType := feed.GetFeedType(ctx.Params(":reponame"), ctx.Req)
|
||||
if isFeed {
|
||||
feed.ShowRepoFeed(ctx, ctx.Repo.Repository, showFeedType)
|
||||
switch {
|
||||
case ctx.Link == fmt.Sprintf("%s.%s", ctx.Repo.RepoLink, showFeedType):
|
||||
feed.ShowRepoFeed(ctx, ctx.Repo.Repository, showFeedType)
|
||||
case ctx.Repo.TreePath == "":
|
||||
feed.ShowBranchFeed(ctx, ctx.Repo.Repository, showFeedType)
|
||||
case ctx.Repo.TreePath != "":
|
||||
feed.ShowFileFeed(ctx, ctx.Repo.Repository, showFeedType)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -868,21 +877,25 @@ func renderRepoTopics(ctx *context.Context) {
|
||||
|
||||
func renderCode(ctx *context.Context) {
|
||||
ctx.Data["PageIsViewCode"] = true
|
||||
ctx.Data["RepositoryUploadEnabled"] = setting.Repository.Upload.Enabled
|
||||
|
||||
if ctx.Repo.Repository.IsEmpty {
|
||||
reallyEmpty := true
|
||||
if ctx.Repo.Commit == nil || ctx.Repo.Repository.IsEmpty || ctx.Repo.Repository.IsBroken() {
|
||||
showEmpty := true
|
||||
var err error
|
||||
if ctx.Repo.GitRepo != nil {
|
||||
reallyEmpty, err = ctx.Repo.GitRepo.IsEmpty()
|
||||
showEmpty, err = ctx.Repo.GitRepo.IsEmpty()
|
||||
if err != nil {
|
||||
ctx.ServerError("GitRepo.IsEmpty", err)
|
||||
return
|
||||
log.Error("GitRepo.IsEmpty: %v", err)
|
||||
ctx.Repo.Repository.Status = repo_model.RepositoryBroken
|
||||
showEmpty = true
|
||||
ctx.Flash.Error(ctx.Tr("error.occurred"), true)
|
||||
}
|
||||
}
|
||||
if reallyEmpty {
|
||||
if showEmpty {
|
||||
ctx.HTML(http.StatusOK, tplRepoEMPTY)
|
||||
return
|
||||
}
|
||||
|
||||
// the repo is not really empty, so we should update the modal in database
|
||||
// such problem may be caused by:
|
||||
// 1) an error occurs during pushing/receiving. 2) the user replaces an empty git repo manually
|
||||
@@ -898,6 +911,14 @@ func renderCode(ctx *context.Context) {
|
||||
ctx.ServerError("UpdateRepoSize", err)
|
||||
return
|
||||
}
|
||||
|
||||
// the repo's IsEmpty has been updated, redirect to this page to make sure middlewares can get the correct values
|
||||
link := ctx.Link
|
||||
if ctx.Req.URL.RawQuery != "" {
|
||||
link += "?" + ctx.Req.URL.RawQuery
|
||||
}
|
||||
ctx.Redirect(link)
|
||||
return
|
||||
}
|
||||
|
||||
title := ctx.Repo.Repository.Owner.Name + "/" + ctx.Repo.Repository.Name
|
||||
@@ -927,11 +948,9 @@ func renderCode(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Repo.Repository.IsEmpty {
|
||||
checkCitationFile(ctx, entry)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
checkCitationFile(ctx, entry)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
renderLanguageStats(ctx)
|
||||
|
||||
+57
-47
@@ -68,9 +68,10 @@ func MustEnableWiki(ctx *context.Context) {
|
||||
|
||||
// PageMeta wiki page meta information
|
||||
type PageMeta struct {
|
||||
Name string
|
||||
SubURL string
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
Name string
|
||||
SubURL string
|
||||
GitEntryName string
|
||||
UpdatedUnix timeutil.TimeStamp
|
||||
}
|
||||
|
||||
// findEntryForFile finds the tree entry for a target filepath.
|
||||
@@ -83,7 +84,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
|
||||
return entry, nil
|
||||
}
|
||||
|
||||
// Then the unescaped, shortest alternative
|
||||
// Then the unescaped, the shortest alternative
|
||||
var unescapedTarget string
|
||||
if unescapedTarget, err = url.QueryUnescape(target); err != nil {
|
||||
return nil, err
|
||||
@@ -124,16 +125,16 @@ func wikiContentsByEntry(ctx *context.Context, entry *git.TreeEntry) []byte {
|
||||
|
||||
// wikiContentsByName returns the contents of a wiki page, along with a boolean
|
||||
// indicating whether the page exists. Writes to ctx if an error occurs.
|
||||
func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) {
|
||||
pageFilename := wiki_service.NameToFilename(wikiName)
|
||||
entry, err := findEntryForFile(commit, pageFilename)
|
||||
func wikiContentsByName(ctx *context.Context, commit *git.Commit, wikiName wiki_service.WebPath) ([]byte, *git.TreeEntry, string, bool) {
|
||||
gitFilename := wiki_service.WebPathToGitPath(wikiName)
|
||||
entry, err := findEntryForFile(commit, gitFilename)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findEntryForFile", err)
|
||||
return nil, nil, "", false
|
||||
} else if entry == nil {
|
||||
return nil, nil, "", true
|
||||
}
|
||||
return wikiContentsByEntry(ctx, entry), entry, pageFilename, false
|
||||
return wikiContentsByEntry(ctx, entry), entry, gitFilename, false
|
||||
}
|
||||
|
||||
func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
@@ -162,7 +163,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
if !entry.IsRegular() {
|
||||
continue
|
||||
}
|
||||
wikiName, err := wiki_service.FilenameToName(entry.Name())
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entry.Name())
|
||||
if err != nil {
|
||||
if repo_model.IsErrWikiInvalidFileName(err) {
|
||||
continue
|
||||
@@ -175,22 +176,26 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
||||
} else if wikiName == "_Sidebar" || wikiName == "_Footer" {
|
||||
continue
|
||||
}
|
||||
_, displayName := wiki_service.WebPathToUserTitle(wikiName)
|
||||
pages = append(pages, PageMeta{
|
||||
Name: wikiName,
|
||||
SubURL: wiki_service.NameToSubURL(wikiName),
|
||||
Name: displayName,
|
||||
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
||||
GitEntryName: entry.Name(),
|
||||
})
|
||||
}
|
||||
ctx.Data["Pages"] = pages
|
||||
|
||||
// get requested pagename
|
||||
pageName := wiki_service.NormalizeWikiName(ctx.Params("*"))
|
||||
// get requested page name
|
||||
pageName := wiki_service.WebPathFromRequest(ctx.Params("*"))
|
||||
if len(pageName) == 0 {
|
||||
pageName = "Home"
|
||||
}
|
||||
ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
|
||||
ctx.Data["old_title"] = pageName
|
||||
ctx.Data["Title"] = pageName
|
||||
ctx.Data["title"] = pageName
|
||||
|
||||
_, displayName := wiki_service.WebPathToUserTitle(pageName)
|
||||
ctx.Data["PageURL"] = wiki_service.WebPathToURLPath(pageName)
|
||||
ctx.Data["old_title"] = displayName
|
||||
ctx.Data["Title"] = displayName
|
||||
ctx.Data["title"] = displayName
|
||||
|
||||
isSideBar := pageName == "_Sidebar"
|
||||
isFooter := pageName == "_Footer"
|
||||
@@ -328,14 +333,17 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
|
||||
}
|
||||
|
||||
// get requested pagename
|
||||
pageName := wiki_service.NormalizeWikiName(ctx.Params("*"))
|
||||
pageName := wiki_service.WebPathFromRequest(ctx.Params("*"))
|
||||
if len(pageName) == 0 {
|
||||
pageName = "Home"
|
||||
}
|
||||
ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
|
||||
ctx.Data["old_title"] = pageName
|
||||
ctx.Data["Title"] = pageName
|
||||
ctx.Data["title"] = pageName
|
||||
|
||||
_, displayName := wiki_service.WebPathToUserTitle(pageName)
|
||||
ctx.Data["PageURL"] = wiki_service.WebPathToURLPath(pageName)
|
||||
ctx.Data["old_title"] = displayName
|
||||
ctx.Data["Title"] = displayName
|
||||
ctx.Data["title"] = displayName
|
||||
|
||||
ctx.Data["Username"] = ctx.Repo.Owner.Name
|
||||
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
||||
|
||||
@@ -403,14 +411,16 @@ func renderEditPage(ctx *context.Context) {
|
||||
}()
|
||||
|
||||
// get requested pagename
|
||||
pageName := wiki_service.NormalizeWikiName(ctx.Params("*"))
|
||||
pageName := wiki_service.WebPathFromRequest(ctx.Params("*"))
|
||||
if len(pageName) == 0 {
|
||||
pageName = "Home"
|
||||
}
|
||||
ctx.Data["PageURL"] = wiki_service.NameToSubURL(pageName)
|
||||
ctx.Data["old_title"] = pageName
|
||||
ctx.Data["Title"] = pageName
|
||||
ctx.Data["title"] = pageName
|
||||
|
||||
_, displayName := wiki_service.WebPathToUserTitle(pageName)
|
||||
ctx.Data["PageURL"] = wiki_service.WebPathToURLPath(pageName)
|
||||
ctx.Data["old_title"] = displayName
|
||||
ctx.Data["Title"] = displayName
|
||||
ctx.Data["title"] = displayName
|
||||
|
||||
// lookup filename in wiki - get filecontent, gitTree entry , real filename
|
||||
data, entry, _, noEntry := wikiContentsByName(ctx, commit, pageName)
|
||||
@@ -594,7 +604,7 @@ func WikiPages(ctx *context.Context) {
|
||||
ctx.ServerError("GetCommit", err)
|
||||
return
|
||||
}
|
||||
wikiName, err := wiki_service.FilenameToName(entry.Name())
|
||||
wikiName, err := wiki_service.GitPathToWebPath(entry.Name())
|
||||
if err != nil {
|
||||
if repo_model.IsErrWikiInvalidFileName(err) {
|
||||
continue
|
||||
@@ -602,10 +612,12 @@ func WikiPages(ctx *context.Context) {
|
||||
ctx.ServerError("WikiFilenameToName", err)
|
||||
return
|
||||
}
|
||||
_, displayName := wiki_service.WebPathToUserTitle(wikiName)
|
||||
pages = append(pages, PageMeta{
|
||||
Name: wikiName,
|
||||
SubURL: wiki_service.NameToSubURL(wikiName),
|
||||
UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()),
|
||||
Name: displayName,
|
||||
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
||||
GitEntryName: entry.Name(),
|
||||
UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()),
|
||||
})
|
||||
}
|
||||
ctx.Data["Pages"] = pages
|
||||
@@ -631,12 +643,12 @@ func WikiRaw(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
providedPath := ctx.Params("*")
|
||||
|
||||
providedWebPath := wiki_service.WebPathFromRequest(ctx.Params("*"))
|
||||
providedGitPath := wiki_service.WebPathToGitPath(providedWebPath)
|
||||
var entry *git.TreeEntry
|
||||
if commit != nil {
|
||||
// Try to find a file with that name
|
||||
entry, err = findEntryForFile(commit, providedPath)
|
||||
entry, err = findEntryForFile(commit, providedGitPath)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
@@ -644,10 +656,8 @@ func WikiRaw(ctx *context.Context) {
|
||||
|
||||
if entry == nil {
|
||||
// Try to find a wiki page with that name
|
||||
providedPath = strings.TrimSuffix(providedPath, ".md")
|
||||
|
||||
wikiPath := wiki_service.NameToFilename(providedPath)
|
||||
entry, err = findEntryForFile(commit, wikiPath)
|
||||
providedGitPath = strings.TrimSuffix(providedGitPath, ".md")
|
||||
entry, err = findEntryForFile(commit, providedGitPath)
|
||||
if err != nil && !git.IsErrNotExist(err) {
|
||||
ctx.ServerError("findFile", err)
|
||||
return
|
||||
@@ -694,7 +704,7 @@ func NewWikiPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
wikiName := wiki_service.NormalizeWikiName(form.Title)
|
||||
wikiName := wiki_service.UserTitleToWebPath("", form.Title)
|
||||
|
||||
if len(form.Message) == 0 {
|
||||
form.Message = ctx.Tr("repo.editor.add", form.Title)
|
||||
@@ -713,9 +723,9 @@ func NewWikiPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
notification.NotifyNewWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.Message)
|
||||
notification.NotifyNewWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, string(wikiName), form.Message)
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.WebPathToURLPath(wikiName))
|
||||
}
|
||||
|
||||
// EditWiki render wiki modify page
|
||||
@@ -745,8 +755,8 @@ func EditWikiPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
oldWikiName := wiki_service.NormalizeWikiName(ctx.Params("*"))
|
||||
newWikiName := wiki_service.NormalizeWikiName(form.Title)
|
||||
oldWikiName := wiki_service.WebPathFromRequest(ctx.Params("*"))
|
||||
newWikiName := wiki_service.UserTitleToWebPath("", form.Title)
|
||||
|
||||
if len(form.Message) == 0 {
|
||||
form.Message = ctx.Tr("repo.editor.update", form.Title)
|
||||
@@ -757,14 +767,14 @@ func EditWikiPost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
notification.NotifyEditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message)
|
||||
notification.NotifyEditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, string(newWikiName), form.Message)
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(newWikiName))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.WebPathToURLPath(newWikiName))
|
||||
}
|
||||
|
||||
// DeleteWikiPagePost delete wiki page
|
||||
func DeleteWikiPagePost(ctx *context.Context) {
|
||||
wikiName := wiki_service.NormalizeWikiName(ctx.Params("*"))
|
||||
wikiName := wiki_service.WebPathFromRequest(ctx.Params("*"))
|
||||
if len(wikiName) == 0 {
|
||||
wikiName = "Home"
|
||||
}
|
||||
@@ -774,7 +784,7 @@ func DeleteWikiPagePost(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
notification.NotifyDeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName)
|
||||
notification.NotifyDeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, string(wikiName))
|
||||
|
||||
ctx.JSON(http.StatusOK, map[string]interface{}{
|
||||
"redirect": ctx.Repo.RepoLink + "/wiki/",
|
||||
|
||||
@@ -6,6 +6,7 @@ package repo
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@@ -24,7 +25,7 @@ const (
|
||||
message = "Wiki commit message for unit tests"
|
||||
)
|
||||
|
||||
func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName string) *git.TreeEntry {
|
||||
func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry {
|
||||
wikiRepo, err := git.OpenRepository(git.DefaultContext, repo.WikiPath())
|
||||
assert.NoError(t, err)
|
||||
defer wikiRepo.Close()
|
||||
@@ -33,14 +34,14 @@ func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName string) *git.
|
||||
entries, err := commit.ListEntries()
|
||||
assert.NoError(t, err)
|
||||
for _, entry := range entries {
|
||||
if entry.Name() == wiki_service.NameToFilename(wikiName) {
|
||||
if entry.Name() == wiki_service.WebPathToGitPath(wikiName) {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func wikiContent(t *testing.T, repo *repo_model.Repository, wikiName string) string {
|
||||
func wikiContent(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) string {
|
||||
entry := wikiEntry(t, repo, wikiName)
|
||||
if !assert.NotNil(t, entry) {
|
||||
return ""
|
||||
@@ -53,11 +54,11 @@ func wikiContent(t *testing.T, repo *repo_model.Repository, wikiName string) str
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
func assertWikiExists(t *testing.T, repo *repo_model.Repository, wikiName string) {
|
||||
func assertWikiExists(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) {
|
||||
assert.NotNil(t, wikiEntry(t, repo, wikiName))
|
||||
}
|
||||
|
||||
func assertWikiNotExists(t *testing.T, repo *repo_model.Repository, wikiName string) {
|
||||
func assertWikiNotExists(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) {
|
||||
assert.Nil(t, wikiEntry(t, repo, wikiName))
|
||||
}
|
||||
|
||||
@@ -124,8 +125,8 @@ func TestNewWikiPost(t *testing.T) {
|
||||
})
|
||||
NewWikiPost(ctx)
|
||||
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
||||
assertWikiExists(t, ctx.Repo.Repository, title)
|
||||
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
|
||||
assertWikiExists(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title))
|
||||
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title)), content)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,8 +177,8 @@ func TestEditWikiPost(t *testing.T) {
|
||||
})
|
||||
EditWikiPost(ctx)
|
||||
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
|
||||
assertWikiExists(t, ctx.Repo.Repository, title)
|
||||
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
|
||||
assertWikiExists(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title))
|
||||
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, wiki_service.UserTitleToWebPath("", title)), content)
|
||||
if title != "Home" {
|
||||
assertWikiNotExists(t, ctx.Repo.Repository, "Home")
|
||||
}
|
||||
@@ -201,17 +202,21 @@ func TestWikiRaw(t *testing.T) {
|
||||
"images/jpeg.jpg": "image/jpeg",
|
||||
"Page With Spaced Name": "text/plain; charset=utf-8",
|
||||
"Page-With-Spaced-Name": "text/plain; charset=utf-8",
|
||||
"Page With Spaced Name.md": "text/plain; charset=utf-8",
|
||||
"Page With Spaced Name.md": "", // there is no "Page With Spaced Name.md" in repo
|
||||
"Page-With-Spaced-Name.md": "text/plain; charset=utf-8",
|
||||
} {
|
||||
unittest.PrepareTestEnv(t)
|
||||
|
||||
ctx := test.MockContext(t, "user2/repo1/wiki/raw/"+filepath)
|
||||
ctx := test.MockContext(t, "user2/repo1/wiki/raw/"+url.PathEscape(filepath))
|
||||
ctx.SetParams("*", filepath)
|
||||
test.LoadUser(t, ctx, 2)
|
||||
test.LoadRepo(t, ctx, 1)
|
||||
WikiRaw(ctx)
|
||||
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
|
||||
assert.EqualValues(t, filetype, ctx.Resp.Header().Get("Content-Type"))
|
||||
if filetype == "" {
|
||||
assert.EqualValues(t, http.StatusNotFound, ctx.Resp.Status(), "filepath: %s", filepath)
|
||||
} else {
|
||||
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status(), "filepath: %s", filepath)
|
||||
assert.EqualValues(t, filetype, ctx.Resp.Header().Get("Content-Type"), "filepath: %s", filepath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL
|
||||
ctx.Redirect(redirectURL)
|
||||
}
|
||||
|
||||
func PerformSecretsDelete(ctx *context.Context, redirectURL string) {
|
||||
func PerformSecretsDelete(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
|
||||
id := ctx.FormInt64("id")
|
||||
|
||||
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id}); err != nil {
|
||||
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id, OwnerID: ownerID, RepoID: repoID}); err != nil {
|
||||
log.Error("Delete secret %d failed: %v", id, err)
|
||||
ctx.Flash.Error(ctx.Tr("secrets.deletion.failed"))
|
||||
} else {
|
||||
|
||||
@@ -63,7 +63,7 @@ func Profile(ctx *context.Context) {
|
||||
|
||||
ctx.Data["Title"] = ctx.ContextUser.DisplayName()
|
||||
ctx.Data["PageIsUserProfile"] = true
|
||||
ctx.Data["Owner"] = ctx.ContextUser
|
||||
ctx.Data["ContextUser"] = ctx.ContextUser
|
||||
ctx.Data["OpenIDs"] = openIDs
|
||||
ctx.Data["IsFollowing"] = isFollowing
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ func Repos(ctx *context.Context) {
|
||||
|
||||
ctx.Data["Repos"] = repos
|
||||
}
|
||||
ctx.Data["Owner"] = ctxUser
|
||||
ctx.Data["ContextUser"] = ctxUser
|
||||
pager := context.NewPagination(count, opts.PageSize, opts.Page, 5)
|
||||
pager.SetDefaultParams(ctx)
|
||||
ctx.Data["Page"] = pager
|
||||
|
||||
@@ -40,6 +40,8 @@ func SecretsPost(ctx *context.Context) {
|
||||
func SecretsDelete(ctx *context.Context) {
|
||||
shared.PerformSecretsDelete(
|
||||
ctx,
|
||||
ctx.Doer.ID,
|
||||
0,
|
||||
setting.AppSubURL+"/user/settings/secrets",
|
||||
)
|
||||
}
|
||||
|
||||
+30
-21
@@ -103,7 +103,7 @@ func buildAuthGroup() *auth_service.Group {
|
||||
func Routes(ctx gocontext.Context) *web.Route {
|
||||
routes := web.NewRoute()
|
||||
|
||||
routes.Use(web.WrapWithPrefix("/assets/", web.Wrap(CorsHandler(), public.AssetsHandlerFunc("/assets/")), "AssetsHandler"))
|
||||
routes.Use(web.MiddlewareWithPrefix("/assets/", CorsHandler(), public.AssetsHandlerFunc("/assets/")))
|
||||
|
||||
sessioner := session.Sessioner(session.Options{
|
||||
Provider: setting.SessionConfig.Provider,
|
||||
@@ -123,8 +123,8 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
routes.Use(Recovery(ctx))
|
||||
|
||||
// We use r.Route here over r.Use because this prevents requests that are not for avatars having to go through this additional handler
|
||||
routes.Route("/avatars/*", "GET, HEAD", storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars))
|
||||
routes.Route("/repo-avatars/*", "GET, HEAD", storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars))
|
||||
routes.RouteMethods("/avatars/*", "GET, HEAD", storageHandler(setting.Avatar.Storage, "avatars", storage.Avatars))
|
||||
routes.RouteMethods("/repo-avatars/*", "GET, HEAD", storageHandler(setting.RepoAvatar.Storage, "repo-avatars", storage.RepoAvatars))
|
||||
|
||||
// for health check - doesn't need to be passed through gzip handler
|
||||
routes.Head("/", func(w http.ResponseWriter, req *http.Request) {
|
||||
@@ -153,7 +153,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
|
||||
if setting.Service.EnableCaptcha {
|
||||
// The captcha http.Handler should only fire on /captcha/* so we can just mount this on that url
|
||||
routes.Route("/captcha/*", "GET,HEAD", append(common, captcha.Captchaer(context.GetImageCaptcha()))...)
|
||||
routes.RouteMethods("/captcha/*", "GET,HEAD", append(common, captcha.Captchaer(context.GetImageCaptcha()))...)
|
||||
}
|
||||
|
||||
if setting.HasRobotsTxt {
|
||||
@@ -228,11 +228,11 @@ func Routes(ctx gocontext.Context) *web.Route {
|
||||
|
||||
// RegisterRoutes register routes
|
||||
func RegisterRoutes(m *web.Route) {
|
||||
reqSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: true})
|
||||
ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView})
|
||||
ignExploreSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView})
|
||||
ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true})
|
||||
reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true})
|
||||
reqSignIn := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignInRequired: true})
|
||||
ignSignIn := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignInRequired: setting.Service.RequireSignInView})
|
||||
ignExploreSignIn := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignInRequired: setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView})
|
||||
ignSignInAndCsrf := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{DisableCSRF: true})
|
||||
reqSignOut := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignOutRequired: true})
|
||||
validation.AddBindingRules()
|
||||
|
||||
linkAccountEnabled := func(ctx *context.Context) {
|
||||
@@ -293,7 +293,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
}
|
||||
|
||||
sitemapEnabled := func(ctx *context.Context) {
|
||||
if !setting.EnableSitemap {
|
||||
if !setting.Other.EnableSitemap {
|
||||
ctx.Error(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
@@ -307,7 +307,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
}
|
||||
|
||||
feedEnabled := func(ctx *context.Context) {
|
||||
if !setting.EnableFeed {
|
||||
if !setting.Other.EnableFeed {
|
||||
ctx.Error(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
@@ -551,7 +551,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
|
||||
m.Get("/avatar/{hash}", user.AvatarByEmailHash)
|
||||
|
||||
adminReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true})
|
||||
adminReq := auth_service.VerifyAuthWithOptions(&auth_service.VerifyOptions{SignInRequired: true, AdminRequired: true})
|
||||
|
||||
// ***** START: Admin *****
|
||||
m.Group("/admin", func() {
|
||||
@@ -706,7 +706,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
default:
|
||||
context_service.UserAssignmentWeb()(ctx)
|
||||
if !ctx.Written() {
|
||||
ctx.Data["EnableFeed"] = setting.EnableFeed
|
||||
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
|
||||
user.Profile(ctx)
|
||||
}
|
||||
}
|
||||
@@ -856,7 +856,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Post("/delete", org.SecretsDelete)
|
||||
})
|
||||
|
||||
m.Route("/delete", "GET,POST", org.SettingsDelete)
|
||||
m.RouteMethods("/delete", "GET,POST", org.SettingsDelete)
|
||||
|
||||
m.Group("/packages", func() {
|
||||
m.Get("", org.Packages)
|
||||
@@ -936,6 +936,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Put("", web.Bind(forms.EditProjectBoardForm{}), org.EditProjectBoard)
|
||||
m.Delete("", org.DeleteProjectBoard)
|
||||
m.Post("/default", org.SetDefaultProjectBoard)
|
||||
m.Post("/unsetdefault", org.UnsetDefaultProjectBoard)
|
||||
|
||||
m.Post("/move", org.MoveIssues)
|
||||
})
|
||||
@@ -1184,7 +1185,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Post("/upload-file", repo.UploadFileToServer)
|
||||
m.Post("/upload-remove", web.Bind(forms.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
|
||||
}, repo.MustBeEditable, repo.MustBeAbleToUpload)
|
||||
}, context.RepoRef(), canEnableEditor, context.RepoMustNotBeArchived(), repo.MustBeNotEmpty)
|
||||
}, context.RepoRef(), canEnableEditor, context.RepoMustNotBeArchived())
|
||||
|
||||
m.Group("/branches", func() {
|
||||
m.Group("/_new", func() {
|
||||
@@ -1197,15 +1198,21 @@ func RegisterRoutes(m *web.Route) {
|
||||
}, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty)
|
||||
}, reqSignIn, context.RepoAssignment, context.UnitTypes())
|
||||
|
||||
// Releases
|
||||
// Tags
|
||||
m.Group("/{username}/{reponame}", func() {
|
||||
m.Group("/tags", func() {
|
||||
m.Get("", repo.TagsList)
|
||||
m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
|
||||
m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
|
||||
}, func(ctx *context.Context) {
|
||||
ctx.Data["EnableFeed"] = setting.EnableFeed
|
||||
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
|
||||
}, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true))
|
||||
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
||||
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
||||
}, reqSignIn, context.RepoAssignment, context.UnitTypes())
|
||||
|
||||
// Releases
|
||||
m.Group("/{username}/{reponame}", func() {
|
||||
m.Group("/releases", func() {
|
||||
m.Get("/", repo.Releases)
|
||||
m.Get("/tag/*", repo.SingleRelease)
|
||||
@@ -1213,7 +1220,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
|
||||
m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom)
|
||||
}, func(ctx *context.Context) {
|
||||
ctx.Data["EnableFeed"] = setting.EnableFeed
|
||||
ctx.Data["EnableFeed"] = setting.Other.EnableFeed
|
||||
}, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true))
|
||||
m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader)
|
||||
m.Group("/releases", func() {
|
||||
@@ -1223,8 +1230,6 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Post("/attachments", repo.UploadReleaseAttachment)
|
||||
m.Post("/attachments/remove", repo.DeleteAttachment)
|
||||
}, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, context.RepoRef())
|
||||
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
||||
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
||||
m.Group("/releases", func() {
|
||||
m.Get("/edit/*", repo.EditRelease)
|
||||
m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost)
|
||||
@@ -1292,6 +1297,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Put("", web.Bind(forms.EditProjectBoardForm{}), repo.EditProjectBoard)
|
||||
m.Delete("", repo.DeleteProjectBoard)
|
||||
m.Post("/default", repo.SetDefaultProjectBoard)
|
||||
m.Post("/unsetdefault", repo.UnSetDefaultProjectBoard)
|
||||
|
||||
m.Post("/move", repo.MoveIssues)
|
||||
})
|
||||
@@ -1448,6 +1454,9 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.Get("/cherry-pick/{sha:([a-f0-9]{7,40})$}", repo.SetEditorconfigIfExists, repo.CherryPick)
|
||||
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
|
||||
|
||||
m.Get("/rss/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed)
|
||||
m.Get("/atom/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed)
|
||||
|
||||
m.Group("/src", func() {
|
||||
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home)
|
||||
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home)
|
||||
@@ -1506,7 +1515,7 @@ func RegisterRoutes(m *web.Route) {
|
||||
m.GetOptions("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject)
|
||||
m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile)
|
||||
m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile)
|
||||
}, ignSignInAndCsrf, context_service.UserAssignmentWeb())
|
||||
}, ignSignInAndCsrf, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context_service.UserAssignmentWeb())
|
||||
})
|
||||
})
|
||||
// ***** END: Repository *****
|
||||
|
||||
Reference in New Issue
Block a user