1
1
mirror of https://github.com/go-gitea/gitea synced 2024-12-22 16:44:26 +00:00

Refactor web routes (#30519)

Re-organize the routes in web.go and use ctx constants instead of `context.UnitTypes()`

---------

Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
wxiaoguang 2024-04-17 16:31:37 +08:00 committed by GitHub
parent 4f276a3363
commit 3e2e76e248
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 394 additions and 377 deletions

View File

@ -174,23 +174,27 @@ func (t *Team) LoadMembers(ctx context.Context) (err error) {
return err return err
} }
// UnitEnabled returns if the team has the given unit type enabled // UnitEnabled returns true if the team has the given unit type enabled
func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool { func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool {
return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone
} }
// UnitAccessMode returns if the team has the given unit type enabled // UnitAccessMode returns the access mode for the given unit type, "none" for non-existent units
func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode { func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode {
accessMode, _ := t.UnitAccessModeEx(ctx, tp)
return accessMode
}
func (t *Team) UnitAccessModeEx(ctx context.Context, tp unit.Type) (accessMode perm.AccessMode, exist bool) {
if err := t.LoadUnits(ctx); err != nil { if err := t.LoadUnits(ctx); err != nil {
log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error()) log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error())
} }
for _, u := range t.Units {
for _, unit := range t.Units { if u.Type == tp {
if unit.Type == tp { return u.AccessMode, true
return unit.AccessMode
} }
} }
return perm.AccessModeNone return perm.AccessModeNone, false
} }
// IsUsableTeamName tests if a name could be as team name // IsUsableTeamName tests if a name could be as team name

View File

@ -102,6 +102,16 @@ func (p *Permission) CanWriteIssuesOrPulls(isPull bool) bool {
return p.CanWrite(unit.TypeIssues) return p.CanWrite(unit.TypeIssues)
} }
func (p *Permission) ReadableUnitTypes() []unit.Type {
types := make([]unit.Type, 0, len(p.Units))
for _, u := range p.Units {
if p.CanRead(u.Type) {
types = append(types, u.Type)
}
}
return types
}
func (p *Permission) LogString() string { func (p *Permission) LogString() string {
format := "<Permission AccessMode=%s, %d Units, %d UnitsMode(s): [ " format := "<Permission AccessMode=%s, %d Units, %d UnitsMode(s): [ "
args := []any{p.AccessMode.String(), len(p.Units), len(p.UnitsMode)} args := []any{p.AccessMode.String(), len(p.Units), len(p.UnitsMode)}
@ -229,12 +239,8 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
for _, u := range repo.Units { for _, u := range repo.Units {
var found bool var found bool
for _, team := range teams { for _, team := range teams {
teamMode := team.UnitAccessMode(ctx, u.Type) if teamMode, exist := team.UnitAccessModeEx(ctx, u.Type); exist {
if teamMode > perm_model.AccessModeNone { perm.UnitsMode[u.Type] = max(perm.UnitsMode[u.Type], teamMode)
m := perm.UnitsMode[u.Type]
if m < teamMode {
perm.UnitsMode[u.Type] = teamMode
}
found = true found = true
} }
} }

View File

@ -721,12 +721,12 @@ func checkHomeCodeViewable(ctx *context.Context) {
} }
var firstUnit *unit_model.Unit var firstUnit *unit_model.Unit
for _, repoUnit := range ctx.Repo.Units { for _, repoUnitType := range ctx.Repo.Permission.ReadableUnitTypes() {
if repoUnit.Type == unit_model.TypeCode { if repoUnitType == unit_model.TypeCode {
return return
} }
unit, ok := unit_model.Units[repoUnit.Type] unit, ok := unit_model.Units[repoUnitType]
if ok && (firstUnit == nil || !firstUnit.IsLessThan(unit)) { if ok && (firstUnit == nil || !firstUnit.IsLessThan(unit)) {
firstUnit = &unit firstUnit = &unit
} }

View File

@ -493,6 +493,7 @@ func registerRoutes(m *web.Route) {
}, explore.Code) }, explore.Code)
m.Get("/topics/search", explore.TopicSearch) m.Get("/topics/search", explore.TopicSearch)
}, ignExploreSignIn) }, ignExploreSignIn)
m.Group("/issues", func() { m.Group("/issues", func() {
m.Get("", user.Issues) m.Get("", user.Issues)
m.Get("/search", repo.SearchIssues) m.Get("/search", repo.SearchIssues)
@ -802,6 +803,7 @@ func registerRoutes(m *web.Route) {
reqRepoCodeReader := context.RequireRepoReader(unit.TypeCode) reqRepoCodeReader := context.RequireRepoReader(unit.TypeCode)
reqRepoReleaseWriter := context.RequireRepoWriter(unit.TypeReleases) reqRepoReleaseWriter := context.RequireRepoWriter(unit.TypeReleases)
reqRepoReleaseReader := context.RequireRepoReader(unit.TypeReleases) reqRepoReleaseReader := context.RequireRepoReader(unit.TypeReleases)
reqRepoWikiReader := context.RequireRepoReader(unit.TypeWiki)
reqRepoWikiWriter := context.RequireRepoWriter(unit.TypeWiki) reqRepoWikiWriter := context.RequireRepoWriter(unit.TypeWiki)
reqRepoIssueReader := context.RequireRepoReader(unit.TypeIssues) reqRepoIssueReader := context.RequireRepoReader(unit.TypeIssues)
reqRepoPullsReader := context.RequireRepoReader(unit.TypePullRequests) reqRepoPullsReader := context.RequireRepoReader(unit.TypePullRequests)
@ -838,12 +840,12 @@ func registerRoutes(m *web.Route) {
} }
} }
// ***** START: Organization *****
m.Group("/org", func() { m.Group("/org", func() {
m.Group("/{org}", func() { m.Group("/{org}", func() {
m.Get("/members", org.Members) m.Get("/members", org.Members)
}, context.OrgAssignment()) }, context.OrgAssignment())
}, ignSignIn) }, ignSignIn)
// end "/org": members
m.Group("/org", func() { m.Group("/org", func() {
m.Group("", func() { m.Group("", func() {
@ -958,9 +960,8 @@ func registerRoutes(m *web.Route) {
}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true)) }, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true))
}, context.OrgAssignment(true, true)) }, context.OrgAssignment(true, true))
}, reqSignIn) }, reqSignIn)
// ***** END: Organization ***** // end "/org": most org routes
// ***** START: Repository *****
m.Group("/repo", func() { m.Group("/repo", func() {
m.Get("/create", repo.Create) m.Get("/create", repo.Create)
m.Post("/create", web.Bind(forms.CreateRepoForm{}), repo.CreatePost) m.Post("/create", web.Bind(forms.CreateRepoForm{}), repo.CreatePost)
@ -968,6 +969,7 @@ func registerRoutes(m *web.Route) {
m.Post("/migrate", web.Bind(forms.MigrateRepoForm{}), repo.MigratePost) m.Post("/migrate", web.Bind(forms.MigrateRepoForm{}), repo.MigratePost)
m.Get("/search", repo.SearchRepo) m.Get("/search", repo.SearchRepo)
}, reqSignIn) }, reqSignIn)
// end "/repo": create, migrate, search
m.Group("/{username}/-", func() { m.Group("/{username}/-", func() {
if setting.Packages.Enabled { if setting.Packages.Enabled {
@ -1008,7 +1010,6 @@ func registerRoutes(m *web.Route) {
m.Put("", web.Bind(forms.EditProjectBoardForm{}), org.EditProjectBoard) m.Put("", web.Bind(forms.EditProjectBoardForm{}), org.EditProjectBoard)
m.Delete("", org.DeleteProjectBoard) m.Delete("", org.DeleteProjectBoard)
m.Post("/default", org.SetDefaultProjectBoard) m.Post("/default", org.SetDefaultProjectBoard)
m.Post("/move", org.MoveIssues) m.Post("/move", org.MoveIssues)
}) })
}) })
@ -1023,125 +1024,152 @@ func registerRoutes(m *web.Route) {
m.Group("", func() { m.Group("", func() {
m.Get("/code", user.CodeSearch) m.Get("/code", user.CodeSearch)
}, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false), individualPermsChecker) }, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false), individualPermsChecker)
}, ignSignIn, context.UserAssignmentWeb(), context.OrgAssignment()) // for "/{username}/-" (packages, projects, code) }, ignSignIn, context.UserAssignmentWeb(), context.OrgAssignment())
// end "/{username}/-": packages, projects, code
m.Group("/{username}/{reponame}/settings", func() {
m.Group("", func() {
m.Combo("").Get(repo_setting.Settings).
Post(web.Bind(forms.RepoSettingForm{}), repo_setting.SettingsPost)
}, repo_setting.SettingsCtxData)
m.Post("/avatar", web.Bind(forms.AvatarForm{}), repo_setting.SettingsAvatar)
m.Post("/avatar/delete", repo_setting.SettingsDeleteAvatar)
m.Group("/collaboration", func() {
m.Combo("").Get(repo_setting.Collaboration).Post(repo_setting.CollaborationPost)
m.Post("/access_mode", repo_setting.ChangeCollaborationAccessMode)
m.Post("/delete", repo_setting.DeleteCollaboration)
m.Group("/team", func() {
m.Post("", repo_setting.AddTeamPost)
m.Post("/delete", repo_setting.DeleteTeam)
})
})
m.Group("/branches", func() {
m.Post("/", repo_setting.SetDefaultBranchPost)
}, repo.MustBeNotEmpty)
m.Group("/branches", func() {
m.Get("/", repo_setting.ProtectedBranchRules)
m.Combo("/edit").Get(repo_setting.SettingsProtectedBranch).
Post(web.Bind(forms.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.SettingsProtectedBranchPost)
m.Post("/{id}/delete", repo_setting.DeleteProtectedBranchRulePost)
}, repo.MustBeNotEmpty)
m.Post("/rename_branch", web.Bind(forms.RenameBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.RenameBranchPost)
m.Group("/tags", func() {
m.Get("", repo_setting.ProtectedTags)
m.Post("", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo_setting.NewProtectedTagPost)
m.Post("/delete", context.RepoMustNotBeArchived(), repo_setting.DeleteProtectedTagPost)
m.Get("/{id}", repo_setting.EditProtectedTag)
m.Post("/{id}", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo_setting.EditProtectedTagPost)
})
m.Group("/hooks/git", func() {
m.Get("", repo_setting.GitHooks)
m.Combo("/{name}").Get(repo_setting.GitHooksEdit).
Post(repo_setting.GitHooksEditPost)
}, context.GitHookService())
m.Group("/hooks", func() {
m.Get("", repo_setting.Webhooks)
m.Post("/delete", repo_setting.DeleteWebhook)
addWebhookAddRoutes()
m.Group("/{id}", func() {
m.Get("", repo_setting.WebHooksEdit)
m.Post("/test", repo_setting.TestWebhook)
m.Post("/replay/{uuid}", repo_setting.ReplayWebhook)
})
addWebhookEditRoutes()
}, webhooksEnabled)
m.Group("/keys", func() {
m.Combo("").Get(repo_setting.DeployKeys).
Post(web.Bind(forms.AddKeyForm{}), repo_setting.DeployKeysPost)
m.Post("/delete", repo_setting.DeleteDeployKey)
})
m.Group("/lfs", func() {
m.Get("/", repo_setting.LFSFiles)
m.Get("/show/{oid}", repo_setting.LFSFileGet)
m.Post("/delete/{oid}", repo_setting.LFSDelete)
m.Get("/pointers", repo_setting.LFSPointerFiles)
m.Post("/pointers/associate", repo_setting.LFSAutoAssociate)
m.Get("/find", repo_setting.LFSFileFind)
m.Group("/locks", func() {
m.Get("/", repo_setting.LFSLocks)
m.Post("/", repo_setting.LFSLockFile)
m.Post("/{lid}/unlock", repo_setting.LFSUnlock)
})
})
m.Group("/actions", func() {
m.Get("", repo_setting.RedirectToDefaultSetting)
addSettingsRunnersRoutes()
addSettingsSecretsRoutes()
addSettingsVariablesRoutes()
}, actions.MustEnableActions)
// the follow handler must be under "settings", otherwise this incomplete repo can't be accessed
m.Group("/migrate", func() {
m.Post("/retry", repo.MigrateRetryPost)
m.Post("/cancel", repo.MigrateCancelPost)
})
},
reqSignIn, context.RepoAssignment, context.RepoRef(), reqRepoAdmin,
ctxDataSet("PageIsRepoSettings", true, "LFSStartServer", setting.LFS.StartServer),
)
// end "/{username}/{reponame}/settings"
// user/org home, including rss feeds
m.Get("/{username}/{reponame}", ignSignIn, context.RepoAssignment, context.RepoRef(), repo.SetEditorconfigIfExists, repo.Home)
m.Group("/{username}/{reponame}", func() { m.Group("/{username}/{reponame}", func() {
m.Group("/settings", func() {
m.Group("", func() {
m.Combo("").Get(repo_setting.Settings).
Post(web.Bind(forms.RepoSettingForm{}), repo_setting.SettingsPost)
}, repo_setting.SettingsCtxData)
m.Post("/avatar", web.Bind(forms.AvatarForm{}), repo_setting.SettingsAvatar)
m.Post("/avatar/delete", repo_setting.SettingsDeleteAvatar)
m.Group("/collaboration", func() {
m.Combo("").Get(repo_setting.Collaboration).Post(repo_setting.CollaborationPost)
m.Post("/access_mode", repo_setting.ChangeCollaborationAccessMode)
m.Post("/delete", repo_setting.DeleteCollaboration)
m.Group("/team", func() {
m.Post("", repo_setting.AddTeamPost)
m.Post("/delete", repo_setting.DeleteTeam)
})
})
m.Group("/branches", func() {
m.Post("/", repo_setting.SetDefaultBranchPost)
}, repo.MustBeNotEmpty)
m.Group("/branches", func() {
m.Get("/", repo_setting.ProtectedBranchRules)
m.Combo("/edit").Get(repo_setting.SettingsProtectedBranch).
Post(web.Bind(forms.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.SettingsProtectedBranchPost)
m.Post("/{id}/delete", repo_setting.DeleteProtectedBranchRulePost)
}, repo.MustBeNotEmpty)
m.Post("/rename_branch", web.Bind(forms.RenameBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.RenameBranchPost)
m.Group("/tags", func() {
m.Get("", repo_setting.ProtectedTags)
m.Post("", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo_setting.NewProtectedTagPost)
m.Post("/delete", context.RepoMustNotBeArchived(), repo_setting.DeleteProtectedTagPost)
m.Get("/{id}", repo_setting.EditProtectedTag)
m.Post("/{id}", web.Bind(forms.ProtectTagForm{}), context.RepoMustNotBeArchived(), repo_setting.EditProtectedTagPost)
})
m.Group("/hooks/git", func() {
m.Get("", repo_setting.GitHooks)
m.Combo("/{name}").Get(repo_setting.GitHooksEdit).
Post(repo_setting.GitHooksEditPost)
}, context.GitHookService())
m.Group("/hooks", func() {
m.Get("", repo_setting.Webhooks)
m.Post("/delete", repo_setting.DeleteWebhook)
addWebhookAddRoutes()
m.Group("/{id}", func() {
m.Get("", repo_setting.WebHooksEdit)
m.Post("/test", repo_setting.TestWebhook)
m.Post("/replay/{uuid}", repo_setting.ReplayWebhook)
})
addWebhookEditRoutes()
}, webhooksEnabled)
m.Group("/keys", func() {
m.Combo("").Get(repo_setting.DeployKeys).
Post(web.Bind(forms.AddKeyForm{}), repo_setting.DeployKeysPost)
m.Post("/delete", repo_setting.DeleteDeployKey)
})
m.Group("/lfs", func() {
m.Get("/", repo_setting.LFSFiles)
m.Get("/show/{oid}", repo_setting.LFSFileGet)
m.Post("/delete/{oid}", repo_setting.LFSDelete)
m.Get("/pointers", repo_setting.LFSPointerFiles)
m.Post("/pointers/associate", repo_setting.LFSAutoAssociate)
m.Get("/find", repo_setting.LFSFileFind)
m.Group("/locks", func() {
m.Get("/", repo_setting.LFSLocks)
m.Post("/", repo_setting.LFSLockFile)
m.Post("/{lid}/unlock", repo_setting.LFSUnlock)
})
})
m.Group("/actions", func() {
m.Get("", repo_setting.RedirectToDefaultSetting)
addSettingsRunnersRoutes()
addSettingsSecretsRoutes()
addSettingsVariablesRoutes()
}, actions.MustEnableActions)
// the follow handler must be under "settings", otherwise this incomplete repo can't be accessed
m.Group("/migrate", func() {
m.Post("/retry", repo.MigrateRetryPost)
m.Post("/cancel", repo.MigrateCancelPost)
})
}, ctxDataSet("PageIsRepoSettings", true, "LFSStartServer", setting.LFS.StartServer))
}, reqSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoAdmin, context.RepoRef())
m.Post("/{username}/{reponame}/action/{action}", reqSignIn, context.RepoAssignment, context.UnitTypes(), repo.Action)
// Grouping for those endpoints not requiring authentication (but should respect ignSignIn)
m.Group("/{username}/{reponame}", func() {
m.Group("/milestone", func() {
m.Get("/{id}", repo.MilestoneIssuesAndPulls)
}, reqRepoIssuesOrPullsReader, context.RepoRef())
m.Get("/find/*", repo.FindFiles) m.Get("/find/*", repo.FindFiles)
m.Group("/tree-list", func() { m.Group("/tree-list", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.TreeList) m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.TreeList)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.TreeList) m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.TreeList)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.TreeList) m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.TreeList)
}) })
m.Get("/compare", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists, ignSignIn, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff) m.Get("/compare", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff)
m.Combo("/compare/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists). m.Combo("/compare/*", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists).
Get(repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff). Get(repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff).
Post(reqSignIn, context.RepoMustNotBeArchived(), reqRepoPullsReader, repo.MustAllowPulls, web.Bind(forms.CreateIssueForm{}), repo.SetWhitespaceBehavior, repo.CompareAndPullRequestPost) Post(reqSignIn, context.RepoMustNotBeArchived(), reqRepoPullsReader, repo.MustAllowPulls, web.Bind(forms.CreateIssueForm{}), repo.SetWhitespaceBehavior, repo.CompareAndPullRequestPost)
}, ignSignIn, context.RepoAssignment, reqRepoCodeReader)
// end "/{username}/{reponame}": find, compare, list (code related)
m.Group("/{username}/{reponame}", func() {
m.Get("/issues/posters", repo.IssuePosters) // it can't use {type:issues|pulls} because it would conflict with other routes like "/pulls/{index}"
m.Get("/pulls/posters", repo.PullPosters)
m.Get("/comments/{id}/attachments", repo.GetCommentAttachments)
m.Get("/labels", repo.RetrieveLabels, repo.Labels)
m.Get("/milestones", repo.Milestones)
m.Get("/milestone/{id}", context.RepoRef(), repo.MilestoneIssuesAndPulls)
m.Group("/{type:issues|pulls}", func() { m.Group("/{type:issues|pulls}", func() {
m.Group("/{index}", func() { m.Group("/{index}", func() {
m.Get("/info", repo.GetIssueInfo) m.Get("/info", repo.GetIssueInfo)
m.Get("/attachments", repo.GetIssueAttachments)
m.Get("/attachments/{uuid}", repo.GetAttachment)
m.Group("/content-history", func() {
m.Get("/overview", repo.GetContentHistoryOverview)
m.Get("/list", repo.GetContentHistoryList)
m.Get("/detail", repo.GetContentHistoryDetail)
})
})
}, context.RepoRef())
}, ignSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader)
// end "/{username}/{reponame}": view milestone, label, issue, pull, etc
m.Group("/{username}/{reponame}", func() {
m.Group("/{type:issues|pulls}", func() {
m.Get("", repo.Issues)
m.Group("/{index}", func() {
m.Get("", repo.ViewIssue)
}) })
}) })
}, ignSignIn, context.RepoAssignment, context.UnitTypes()) // for "/{username}/{reponame}" which doesn't require authentication }, ignSignIn, context.RepoAssignment, context.RequireRepoReaderOr(unit.TypeIssues, unit.TypePullRequests, unit.TypeExternalTracker))
// end "/{username}/{reponame}": issue/pull list, issue/pull view, external tracker
// Grouping for those endpoints that do require authentication m.Group("/{username}/{reponame}", func() { // edit issues, pulls, labels, milestones, etc
m.Group("/{username}/{reponame}", func() {
m.Group("/issues", func() { m.Group("/issues", func() {
m.Group("/new", func() { m.Group("/new", func() {
m.Combo("").Get(context.RepoRef(), repo.NewIssue). m.Combo("").Get(context.RepoRef(), repo.NewIssue).
@ -1150,6 +1178,7 @@ func registerRoutes(m *web.Route) {
}) })
m.Get("/search", repo.ListIssues) m.Get("/search", repo.ListIssues)
}, context.RepoMustNotBeArchived(), reqRepoIssueReader) }, context.RepoMustNotBeArchived(), reqRepoIssueReader)
// FIXME: should use different URLs but mostly same logic for comments of issue and pull request. // FIXME: should use different URLs but mostly same logic for comments of issue and pull request.
// So they can apply their own enable/disable logic on routers. // So they can apply their own enable/disable logic on routers.
m.Group("/{type:issues|pulls}", func() { m.Group("/{type:issues|pulls}", func() {
@ -1179,10 +1208,7 @@ func registerRoutes(m *web.Route) {
m.Post("/unlock", reqRepoIssuesOrPullsWriter, repo.UnlockIssue) m.Post("/unlock", reqRepoIssuesOrPullsWriter, repo.UnlockIssue)
m.Post("/delete", reqRepoAdmin, repo.DeleteIssue) m.Post("/delete", reqRepoAdmin, repo.DeleteIssue)
}, context.RepoMustNotBeArchived()) }, context.RepoMustNotBeArchived())
m.Group("/{index}", func() {
m.Get("/attachments", repo.GetIssueAttachments)
m.Get("/attachments/{uuid}", repo.GetAttachment)
})
m.Group("/{index}", func() { m.Group("/{index}", func() {
m.Post("/content-history/soft-delete", repo.SoftDeleteContentHistory) m.Post("/content-history/soft-delete", repo.SoftDeleteContentHistory)
}) })
@ -1191,25 +1217,25 @@ func registerRoutes(m *web.Route) {
m.Post("/milestone", reqRepoIssuesOrPullsWriter, repo.UpdateIssueMilestone) m.Post("/milestone", reqRepoIssuesOrPullsWriter, repo.UpdateIssueMilestone)
m.Post("/projects", reqRepoIssuesOrPullsWriter, reqRepoProjectsReader, repo.UpdateIssueProject) m.Post("/projects", reqRepoIssuesOrPullsWriter, reqRepoProjectsReader, repo.UpdateIssueProject)
m.Post("/assignee", reqRepoIssuesOrPullsWriter, repo.UpdateIssueAssignee) m.Post("/assignee", reqRepoIssuesOrPullsWriter, repo.UpdateIssueAssignee)
m.Post("/request_review", reqRepoIssuesOrPullsReader, repo.UpdatePullReviewRequest) m.Post("/request_review", repo.UpdatePullReviewRequest)
m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview) m.Post("/dismiss_review", reqRepoAdmin, web.Bind(forms.DismissReviewForm{}), repo.DismissReview)
m.Post("/status", reqRepoIssuesOrPullsWriter, repo.UpdateIssueStatus) m.Post("/status", reqRepoIssuesOrPullsWriter, repo.UpdateIssueStatus)
m.Post("/delete", reqRepoAdmin, repo.BatchDeleteIssues) m.Post("/delete", reqRepoAdmin, repo.BatchDeleteIssues)
m.Post("/resolve_conversation", reqRepoIssuesOrPullsReader, repo.SetShowOutdatedComments, repo.UpdateResolveConversation) m.Post("/resolve_conversation", repo.SetShowOutdatedComments, repo.UpdateResolveConversation)
m.Post("/attachments", repo.UploadIssueAttachment) m.Post("/attachments", repo.UploadIssueAttachment)
m.Post("/attachments/remove", repo.DeleteAttachment) m.Post("/attachments/remove", repo.DeleteAttachment)
m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin) m.Delete("/unpin/{index}", reqRepoAdmin, repo.IssueUnpin)
m.Post("/move_pin", reqRepoAdmin, repo.IssuePinMove) m.Post("/move_pin", reqRepoAdmin, repo.IssuePinMove)
}, context.RepoMustNotBeArchived()) }, context.RepoMustNotBeArchived())
m.Group("/comments/{id}", func() { m.Group("/comments/{id}", func() {
m.Post("", repo.UpdateCommentContent) m.Post("", repo.UpdateCommentContent)
m.Post("/delete", repo.DeleteComment) m.Post("/delete", repo.DeleteComment)
m.Post("/reactions/{action}", web.Bind(forms.ReactionForm{}), repo.ChangeCommentReaction) m.Post("/reactions/{action}", web.Bind(forms.ReactionForm{}), repo.ChangeCommentReaction)
}, context.RepoMustNotBeArchived()) }, context.RepoMustNotBeArchived())
m.Group("/comments/{id}", func() {
m.Get("/attachments", repo.GetCommentAttachments)
})
m.Post("/markup", web.Bind(structs.MarkupOption{}), misc.Markup) m.Post("/markup", web.Bind(structs.MarkupOption{}), misc.Markup)
m.Group("/labels", func() { m.Group("/labels", func() {
m.Post("/new", web.Bind(forms.CreateLabelForm{}), repo.NewLabel) m.Post("/new", web.Bind(forms.CreateLabelForm{}), repo.NewLabel)
m.Post("/edit", web.Bind(forms.CreateLabelForm{}), repo.UpdateLabel) m.Post("/edit", web.Bind(forms.CreateLabelForm{}), repo.UpdateLabel)
@ -1227,7 +1253,10 @@ func registerRoutes(m *web.Route) {
m.Group("/pull", func() { m.Group("/pull", func() {
m.Post("/{index}/target_branch", repo.UpdatePullRequestTarget) m.Post("/{index}/target_branch", repo.UpdatePullRequestTarget)
}, context.RepoMustNotBeArchived()) }, context.RepoMustNotBeArchived())
}, reqSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader)
// end "/{username}/{reponame}": create or edit issues, pulls, labels, milestones
m.Group("/{username}/{reponame}", func() { // repo code
m.Group("", func() { m.Group("", func() {
m.Group("", func() { m.Group("", func() {
m.Combo("/_edit/*").Get(repo.EditFile). m.Combo("/_edit/*").Get(repo.EditFile).
@ -1261,26 +1290,26 @@ func registerRoutes(m *web.Route) {
m.Post("/restore", repo.RestoreBranchPost) m.Post("/restore", repo.RestoreBranchPost)
}, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty) }, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty)
m.Combo("/fork", reqRepoCodeReader).Get(repo.Fork).Post(web.Bind(forms.CreateRepoForm{}), repo.ForkPost) m.Combo("/fork").Get(repo.Fork).Post(web.Bind(forms.CreateRepoForm{}), repo.ForkPost)
}, reqSignIn, context.RepoAssignment, context.UnitTypes()) }, reqSignIn, context.RepoAssignment, reqRepoCodeReader)
// end "/{username}/{reponame}": repo code
// Tags m.Group("/{username}/{reponame}", func() { // repo tags
m.Group("/{username}/{reponame}", func() {
m.Group("/tags", func() { m.Group("/tags", func() {
m.Get("", repo.TagsList) m.Get("", repo.TagsList)
m.Get("/list", repo.GetTagList) m.Get("/list", repo.GetTagList)
m.Get(".rss", feedEnabled, repo.TagsListFeedRSS) m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
m.Get(".atom", feedEnabled, repo.TagsListFeedAtom) m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed), }, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true)) repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, true))
m.Post("/tags/delete", repo.DeleteTag, reqSignIn, m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef()) repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
}, ignSignIn, context.RepoAssignment, context.UnitTypes()) }, ignSignIn, context.RepoAssignment, reqRepoCodeReader)
// end "/{username}/{reponame}": repo tags
// Releases m.Group("/{username}/{reponame}", func() { // repo releases
m.Group("/{username}/{reponame}", func() {
m.Group("/releases", func() { m.Group("/releases", func() {
m.Get("/", repo.Releases) m.Get("", repo.Releases)
m.Get("/tag/*", repo.SingleRelease) m.Get("/tag/*", repo.SingleRelease)
m.Get("/latest", repo.LatestRelease) m.Get("/latest", repo.LatestRelease)
m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS) m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
@ -1300,148 +1329,141 @@ func registerRoutes(m *web.Route) {
m.Get("/edit/*", repo.EditRelease) m.Get("/edit/*", repo.EditRelease)
m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost) m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost)
}, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, repo.CommitInfoCache) }, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, repo.CommitInfoCache)
}, ignSignIn, context.RepoAssignment, context.UnitTypes(), reqRepoReleaseReader) }, ignSignIn, context.RepoAssignment, reqRepoReleaseReader)
// end "/{username}/{reponame}": repo releases
// to maintain compatibility with old attachments m.Group("/{username}/{reponame}", func() { // to maintain compatibility with old attachments
m.Group("/{username}/{reponame}", func() {
m.Get("/attachments/{uuid}", repo.GetAttachment) m.Get("/attachments/{uuid}", repo.GetAttachment)
}, ignSignIn, context.RepoAssignment, context.UnitTypes()) }, ignSignIn, context.RepoAssignment)
// end "/{username}/{reponame}": compatibility with old attachments
m.Group("/{username}/{reponame}", func() { m.Group("/{username}/{reponame}", func() {
m.Post("/topics", repo.TopicsPost) m.Post("/topics", repo.TopicsPost)
}, context.RepoAssignment, context.RepoMustNotBeArchived(), reqRepoAdmin) }, context.RepoAssignment, reqRepoAdmin, context.RepoMustNotBeArchived())
m.Group("/{username}/{reponame}", func() { m.Group("/{username}/{reponame}", func() {
m.Group("", func() {
m.Get("/issues/posters", repo.IssuePosters) // it can't use {type:issues|pulls} because other routes like "/pulls/{index}" has higher priority
m.Get("/{type:issues|pulls}", repo.Issues)
m.Get("/{type:issues|pulls}/{index}", repo.ViewIssue)
m.Group("/{type:issues|pulls}/{index}/content-history", func() {
m.Get("/overview", repo.GetContentHistoryOverview)
m.Get("/list", repo.GetContentHistoryList)
m.Get("/detail", repo.GetContentHistoryDetail)
})
m.Get("/labels", reqRepoIssuesOrPullsReader, repo.RetrieveLabels, repo.Labels)
m.Get("/milestones", reqRepoIssuesOrPullsReader, repo.Milestones)
}, context.RepoRef())
if setting.Packages.Enabled { if setting.Packages.Enabled {
m.Get("/packages", repo.Packages) m.Get("/packages", repo.Packages)
} }
}, ignSignIn, context.RepoAssignment)
m.Group("/projects", func() { m.Group("/{username}/{reponame}/projects", func() {
m.Get("", repo.Projects) m.Get("", repo.Projects)
m.Get("/{id}", repo.ViewProject) m.Get("/{id}", repo.ViewProject)
m.Group("", func() { //nolint:dupl m.Group("", func() { //nolint:dupl
m.Get("/new", repo.RenderNewProject) m.Get("/new", repo.RenderNewProject)
m.Post("/new", web.Bind(forms.CreateProjectForm{}), repo.NewProjectPost) m.Post("/new", web.Bind(forms.CreateProjectForm{}), repo.NewProjectPost)
m.Group("/{id}", func() { m.Group("/{id}", func() {
m.Post("", web.Bind(forms.EditProjectBoardForm{}), repo.AddBoardToProjectPost) m.Post("", web.Bind(forms.EditProjectBoardForm{}), repo.AddBoardToProjectPost)
m.Post("/delete", repo.DeleteProject) m.Post("/delete", repo.DeleteProject)
m.Get("/edit", repo.RenderEditProject) m.Get("/edit", repo.RenderEditProject)
m.Post("/edit", web.Bind(forms.CreateProjectForm{}), repo.EditProjectPost) m.Post("/edit", web.Bind(forms.CreateProjectForm{}), repo.EditProjectPost)
m.Post("/{action:open|close}", repo.ChangeProjectStatus) m.Post("/{action:open|close}", repo.ChangeProjectStatus)
m.Group("/{boardID}", func() { m.Group("/{boardID}", func() {
m.Put("", web.Bind(forms.EditProjectBoardForm{}), repo.EditProjectBoard) m.Put("", web.Bind(forms.EditProjectBoardForm{}), repo.EditProjectBoard)
m.Delete("", repo.DeleteProjectBoard) m.Delete("", repo.DeleteProjectBoard)
m.Post("/default", repo.SetDefaultProjectBoard) m.Post("/default", repo.SetDefaultProjectBoard)
m.Post("/move", repo.MoveIssues)
m.Post("/move", repo.MoveIssues)
})
}) })
}, reqRepoProjectsWriter, context.RepoMustNotBeArchived()) })
}, reqRepoProjectsReader, repo.MustEnableRepoProjects) }, reqRepoProjectsWriter, context.RepoMustNotBeArchived())
}, ignSignIn, context.RepoAssignment, reqRepoProjectsReader, repo.MustEnableRepoProjects)
// end "/{username}/{reponame}/projects"
m.Group("/actions", func() { m.Group("/{username}/{reponame}/actions", func() {
m.Get("", actions.List) m.Get("", actions.List)
m.Post("/disable", reqRepoAdmin, actions.DisableWorkflowFile) m.Post("/disable", reqRepoAdmin, actions.DisableWorkflowFile)
m.Post("/enable", reqRepoAdmin, actions.EnableWorkflowFile) m.Post("/enable", reqRepoAdmin, actions.EnableWorkflowFile)
m.Group("/runs/{run}", func() { m.Group("/runs/{run}", func() {
m.Combo("").
Get(actions.View).
Post(web.Bind(actions.ViewRequest{}), actions.ViewPost)
m.Group("/jobs/{job}", func() {
m.Combo(""). m.Combo("").
Get(actions.View). Get(actions.View).
Post(web.Bind(actions.ViewRequest{}), actions.ViewPost) Post(web.Bind(actions.ViewRequest{}), actions.ViewPost)
m.Group("/jobs/{job}", func() {
m.Combo("").
Get(actions.View).
Post(web.Bind(actions.ViewRequest{}), actions.ViewPost)
m.Post("/rerun", reqRepoActionsWriter, actions.Rerun)
m.Get("/logs", actions.Logs)
})
m.Post("/cancel", reqRepoActionsWriter, actions.Cancel)
m.Post("/approve", reqRepoActionsWriter, actions.Approve)
m.Get("/artifacts", actions.ArtifactsView)
m.Get("/artifacts/{artifact_name}", actions.ArtifactsDownloadView)
m.Delete("/artifacts/{artifact_name}", actions.ArtifactsDeleteView)
m.Post("/rerun", reqRepoActionsWriter, actions.Rerun) m.Post("/rerun", reqRepoActionsWriter, actions.Rerun)
m.Get("/logs", actions.Logs)
}) })
m.Group("/workflows/{workflow_name}", func() { m.Post("/cancel", reqRepoActionsWriter, actions.Cancel)
m.Get("/badge.svg", actions.GetWorkflowBadge) m.Post("/approve", reqRepoActionsWriter, actions.Approve)
}) m.Get("/artifacts", actions.ArtifactsView)
}, reqRepoActionsReader, actions.MustEnableActions) m.Get("/artifacts/{artifact_name}", actions.ArtifactsDownloadView)
m.Delete("/artifacts/{artifact_name}", actions.ArtifactsDeleteView)
m.Group("/wiki", func() { m.Post("/rerun", reqRepoActionsWriter, actions.Rerun)
m.Combo("/").
Get(repo.Wiki).
Post(context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost)
m.Combo("/*").
Get(repo.Wiki).
Post(context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost)
m.Get("/commit/{sha:[a-f0-9]{7,64}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
m.Get("/commit/{sha:[a-f0-9]{7,64}}.{ext:patch|diff}", repo.RawDiff)
}, repo.MustEnableWiki, func(ctx *context.Context) {
ctx.Data["PageIsWiki"] = true
ctx.Data["CloneButtonOriginLink"] = ctx.Repo.Repository.WikiCloneLink()
}) })
m.Group("/workflows/{workflow_name}", func() {
m.Get("/badge.svg", actions.GetWorkflowBadge)
})
}, ignSignIn, context.RepoAssignment, reqRepoActionsReader, actions.MustEnableActions)
// end "/{username}/{reponame}/actions"
m.Group("/wiki", func() { m.Group("/{username}/{reponame}/wiki", func() {
m.Get("/raw/*", repo.WikiRaw) m.Combo("").
}, repo.MustEnableWiki) Get(repo.Wiki).
Post(context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost)
m.Combo("/*").
Get(repo.Wiki).
Post(context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost)
m.Get("/commit/{sha:[a-f0-9]{7,64}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
m.Get("/commit/{sha:[a-f0-9]{7,64}}.{ext:patch|diff}", repo.RawDiff)
m.Get("/raw/*", repo.WikiRaw)
}, ignSignIn, context.RepoAssignment, repo.MustEnableWiki, reqRepoWikiReader, func(ctx *context.Context) {
ctx.Data["PageIsWiki"] = true
ctx.Data["CloneButtonOriginLink"] = ctx.Repo.Repository.WikiCloneLink()
})
// end "/{username}/{reponame}/wiki"
m.Group("/activity", func() { m.Group("/{username}/{reponame}/activity", func() {
m.Get("", repo.Activity) m.Get("", repo.Activity)
m.Get("/{period}", repo.Activity) m.Get("/{period}", repo.Activity)
m.Group("/contributors", func() { m.Group("/contributors", func() {
m.Get("", repo.Contributors) m.Get("", repo.Contributors)
m.Get("/data", repo.ContributorsData) m.Get("/data", repo.ContributorsData)
}) })
m.Group("/code-frequency", func() { m.Group("/code-frequency", func() {
m.Get("", repo.CodeFrequency) m.Get("", repo.CodeFrequency)
m.Get("/data", repo.CodeFrequencyData) m.Get("/data", repo.CodeFrequencyData)
}) })
m.Group("/recent-commits", func() { m.Group("/recent-commits", func() {
m.Get("", repo.RecentCommits) m.Get("", repo.RecentCommits)
m.Get("/data", repo.RecentCommitsData) m.Get("/data", repo.RecentCommitsData)
}) })
}, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypePullRequests, unit.TypeIssues, unit.TypeReleases)) },
ignSignIn, context.RepoAssignment, context.RequireRepoReaderOr(unit.TypePullRequests, unit.TypeIssues, unit.TypeReleases),
context.RepoRef(), repo.MustBeNotEmpty,
)
// end "/{username}/{reponame}/activity"
m.Group("/{username}/{reponame}", func() {
m.Group("/activity_author_data", func() { m.Group("/activity_author_data", func() {
m.Get("", repo.ActivityAuthors) m.Get("", repo.ActivityAuthors)
m.Get("/{period}", repo.ActivityAuthors) m.Get("/{period}", repo.ActivityAuthors)
}, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(unit.TypeCode)) }, context.RepoRef(), repo.MustBeNotEmpty)
m.Group("/archive", func() { m.Group("/archive", func() {
m.Get("/*", repo.Download) m.Get("/*", repo.Download)
m.Post("/*", repo.InitiateDownload) m.Post("/*", repo.InitiateDownload)
}, repo.MustBeNotEmpty, dlSourceEnabled, reqRepoCodeReader) }, repo.MustBeNotEmpty, dlSourceEnabled)
m.Group("/branches", func() { m.Group("/branches", func() {
m.Get("/list", repo.GetBranchesList) m.Get("/list", repo.GetBranchesList)
m.Get("", repo.Branches) m.Get("", repo.Branches)
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader) }, repo.MustBeNotEmpty, context.RepoRef())
m.Group("/blob_excerpt", func() { m.Group("/blob_excerpt", func() {
m.Get("/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob) m.Get("/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob)
}, func(ctx *context.Context) gocontext.CancelFunc { }, func(ctx *context.Context) gocontext.CancelFunc {
// FIXME: refactor this function, use separate routes for wiki/code
if ctx.FormBool("wiki") { if ctx.FormBool("wiki") {
ctx.Data["PageIsWiki"] = true ctx.Data["PageIsWiki"] = true
repo.MustEnableWiki(ctx) repo.MustEnableWiki(ctx)
return nil return nil
} }
reqRepoCodeReader(ctx)
if ctx.Written() { if ctx.Written() {
return nil return nil
} }
@ -1454,7 +1476,6 @@ func registerRoutes(m *web.Route) {
return cancel return cancel
}) })
m.Get("/pulls/posters", repo.PullPosters)
m.Group("/pulls/{index}", func() { m.Group("/pulls/{index}", func() {
m.Get("", repo.SetWhitespaceBehavior, repo.GetPullDiffStats, repo.ViewIssue) m.Get("", repo.SetWhitespaceBehavior, repo.GetPullDiffStats, repo.ViewIssue)
m.Get(".diff", repo.DownloadPullDiff) m.Get(".diff", repo.DownloadPullDiff)
@ -1488,7 +1509,7 @@ func registerRoutes(m *web.Route) {
m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByIDOrLFS) m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByIDOrLFS)
// "/*" route is deprecated, and kept for backward compatibility // "/*" route is deprecated, and kept for backward compatibility
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.SingleDownloadOrLFS) m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.SingleDownloadOrLFS)
}, repo.MustBeNotEmpty, reqRepoCodeReader) }, repo.MustBeNotEmpty)
m.Group("/raw", func() { m.Group("/raw", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.SingleDownload) m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.SingleDownload)
@ -1497,14 +1518,14 @@ func registerRoutes(m *web.Route) {
m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByID) m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByID)
// "/*" route is deprecated, and kept for backward compatibility // "/*" route is deprecated, and kept for backward compatibility
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.SingleDownload) m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.SingleDownload)
}, repo.MustBeNotEmpty, reqRepoCodeReader) }, repo.MustBeNotEmpty)
m.Group("/render", func() { m.Group("/render", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RenderFile) m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RenderFile)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RenderFile) m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RenderFile)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RenderFile) m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RenderFile)
m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.RenderFile) m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.RenderFile)
}, repo.MustBeNotEmpty, reqRepoCodeReader) }, repo.MustBeNotEmpty)
m.Group("/commits", func() { m.Group("/commits", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RefCommits) m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RefCommits)
@ -1512,20 +1533,20 @@ func registerRoutes(m *web.Route) {
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefCommits) m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefCommits)
// "/*" route is deprecated, and kept for backward compatibility // "/*" route is deprecated, and kept for backward compatibility
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.RefCommits) m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.RefCommits)
}, repo.MustBeNotEmpty, reqRepoCodeReader) }, repo.MustBeNotEmpty)
m.Group("/blame", func() { m.Group("/blame", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RefBlame) m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RefBlame)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RefBlame) m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RefBlame)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefBlame) m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefBlame)
}, repo.MustBeNotEmpty, reqRepoCodeReader) }, repo.MustBeNotEmpty)
m.Group("", func() { m.Group("", func() {
m.Get("/graph", repo.Graph) m.Get("/graph", repo.Graph)
m.Get("/commit/{sha:([a-f0-9]{7,64})$}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff) m.Get("/commit/{sha:([a-f0-9]{7,64})$}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
m.Get("/commit/{sha:([a-f0-9]{7,64})$}/load-branches-and-tags", repo.LoadBranchesAndTags) m.Get("/commit/{sha:([a-f0-9]{7,64})$}/load-branches-and-tags", repo.LoadBranchesAndTags)
m.Get("/cherry-pick/{sha:([a-f0-9]{7,64})$}", repo.SetEditorconfigIfExists, repo.CherryPick) m.Get("/cherry-pick/{sha:([a-f0-9]{7,64})$}", repo.SetEditorconfigIfExists, repo.CherryPick)
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader) }, repo.MustBeNotEmpty, context.RepoRef())
m.Get("/rss/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed) m.Get("/rss/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed)
m.Get("/atom/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed) m.Get("/atom/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed)
@ -1534,51 +1555,42 @@ func registerRoutes(m *web.Route) {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home) m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home) m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.Home) m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.Home)
// "/*" route is deprecated, and kept for backward compatibility m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.Home) // "/*" route is deprecated, and kept for backward compatibility
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.Home)
}, repo.SetEditorconfigIfExists) }, repo.SetEditorconfigIfExists)
m.Group("", func() { m.Get("/forks", context.RepoRef(), repo.Forks)
m.Get("/forks", repo.Forks) m.Get("/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}", repo.MustBeNotEmpty, repo.RawDiff)
}, context.RepoRef(), reqRepoCodeReader) m.Post("/lastcommit/*", context.RepoRefByType(context.RepoRefCommit), repo.LastCommit)
m.Get("/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}", repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff) }, ignSignIn, context.RepoAssignment, reqRepoCodeReader)
}, ignSignIn, context.RepoAssignment, context.UnitTypes()) // end "/{username}/{reponame}": repo code
m.Post("/{username}/{reponame}/lastcommit/*", ignSignInAndCsrf, context.RepoAssignment, context.UnitTypes(), context.RepoRefByType(context.RepoRefCommit), reqRepoCodeReader, repo.LastCommit)
m.Group("/{username}/{reponame}", func() { m.Group("/{username}/{reponame}", func() {
m.Get("/stars", repo.Stars) m.Get("/stars", repo.Stars)
m.Get("/watchers", repo.Watchers) m.Get("/watchers", repo.Watchers)
m.Get("/search", reqRepoCodeReader, repo.Search) m.Get("/search", reqRepoCodeReader, repo.Search)
}, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes()) m.Post("/action/{action}", reqSignIn, repo.Action)
}, ignSignIn, context.RepoAssignment, context.RepoRef())
m.Group("/{username}", func() { m.Group("/{username}/{reponame}", func() {
m.Group("/{reponame}", func() { m.Group("/info/lfs", func() {
m.Get("", repo.SetEditorconfigIfExists, repo.Home) m.Post("/objects/batch", lfs.CheckAcceptMediaType, lfs.BatchHandler)
}, ignSignIn, context.RepoAssignment, context.RepoRef(), context.UnitTypes()) m.Put("/objects/{oid}/{size}", lfs.UploadHandler)
m.Get("/objects/{oid}/{filename}", lfs.DownloadHandler)
m.Group("/{reponame}", func() { m.Get("/objects/{oid}", lfs.DownloadHandler)
m.Group("/info/lfs", func() { m.Post("/verify", lfs.CheckAcceptMediaType, lfs.VerifyHandler)
m.Post("/objects/batch", lfs.CheckAcceptMediaType, lfs.BatchHandler) m.Group("/locks", func() {
m.Put("/objects/{oid}/{size}", lfs.UploadHandler) m.Get("/", lfs.GetListLockHandler)
m.Get("/objects/{oid}/{filename}", lfs.DownloadHandler) m.Post("/", lfs.PostLockHandler)
m.Get("/objects/{oid}", lfs.DownloadHandler) m.Post("/verify", lfs.VerifyLockHandler)
m.Post("/verify", lfs.CheckAcceptMediaType, lfs.VerifyHandler) m.Post("/{lid}/unlock", lfs.UnLockHandler)
m.Group("/locks", func() { }, lfs.CheckAcceptMediaType)
m.Get("/", lfs.GetListLockHandler) m.Any("/*", func(ctx *context.Context) {
m.Post("/", lfs.PostLockHandler) ctx.NotFound("", nil)
m.Post("/verify", lfs.VerifyLockHandler) })
m.Post("/{lid}/unlock", lfs.UnLockHandler) }, ignSignInAndCsrf, lfsServerEnabled)
}, lfs.CheckAcceptMediaType) gitHTTPRouters(m)
m.Any("/*", func(ctx *context.Context) {
ctx.NotFound("", nil)
})
}, ignSignInAndCsrf, lfsServerEnabled)
gitHTTPRouters(m)
})
}) })
// ***** END: Repository ***** // end "/{username}/{reponame}.git": git support
m.Group("/notifications", func() { m.Group("/notifications", func() {
m.Get("", user.Notifications) m.Get("", user.Notifications)

View File

@ -102,6 +102,18 @@ func NewTemplateContextForWeb(ctx *Context) TemplateContext {
tmplCtx["Locale"] = ctx.Base.Locale tmplCtx["Locale"] = ctx.Base.Locale
tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx) tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx)
tmplCtx["RootData"] = ctx.Data tmplCtx["RootData"] = ctx.Data
tmplCtx["Consts"] = map[string]any{
"RepoUnitTypeCode": unit.TypeCode,
"RepoUnitTypeIssues": unit.TypeIssues,
"RepoUnitTypePullRequests": unit.TypePullRequests,
"RepoUnitTypeReleases": unit.TypeReleases,
"RepoUnitTypeWiki": unit.TypeWiki,
"RepoUnitTypeExternalWiki": unit.TypeExternalWiki,
"RepoUnitTypeExternalTracker": unit.TypeExternalTracker,
"RepoUnitTypeProjects": unit.TypeProjects,
"RepoUnitTypePackages": unit.TypePackages,
"RepoUnitTypeActions": unit.TypeActions,
}
return tmplCtx return tmplCtx
} }

View File

@ -383,7 +383,6 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
ctx.NotFound("no access right", nil) ctx.NotFound("no access right", nil)
return return
} }
ctx.Data["HasAccess"] = true
ctx.Data["Permission"] = &ctx.Repo.Permission ctx.Data["Permission"] = &ctx.Repo.Permission
if repo.IsMirror { if repo.IsMirror {
@ -1052,19 +1051,3 @@ func GitHookService() func(ctx *Context) {
} }
} }
} }
// UnitTypes returns a middleware to set unit types to context variables.
func UnitTypes() func(ctx *Context) {
return func(ctx *Context) {
ctx.Data["UnitTypeCode"] = unit_model.TypeCode
ctx.Data["UnitTypeIssues"] = unit_model.TypeIssues
ctx.Data["UnitTypePullRequests"] = unit_model.TypePullRequests
ctx.Data["UnitTypeReleases"] = unit_model.TypeReleases
ctx.Data["UnitTypeWiki"] = unit_model.TypeWiki
ctx.Data["UnitTypeExternalWiki"] = unit_model.TypeExternalWiki
ctx.Data["UnitTypeExternalTracker"] = unit_model.TypeExternalTracker
ctx.Data["UnitTypeProjects"] = unit_model.TypeProjects
ctx.Data["UnitTypePackages"] = unit_model.TypePackages
ctx.Data["UnitTypeActions"] = unit_model.TypeActions
}
}

View File

@ -11,7 +11,7 @@
<a class="{{if .PageIsExploreOrganizations}}active {{end}}item" href="{{AppSubUrl}}/explore/organizations"> <a class="{{if .PageIsExploreOrganizations}}active {{end}}item" href="{{AppSubUrl}}/explore/organizations">
{{svg "octicon-organization"}} {{ctx.Locale.Tr "explore.organizations"}} {{svg "octicon-organization"}} {{ctx.Locale.Tr "explore.organizations"}}
</a> </a>
{{if and (not $.UnitTypeCode.UnitGlobalDisabled) .IsRepoIndexerEnabled}} {{if and (not ctx.Consts.RepoUnitTypeCode.UnitGlobalDisabled) .IsRepoIndexerEnabled}}
<a class="{{if .PageIsExploreCode}}active {{end}}item" href="{{AppSubUrl}}/explore/code"> <a class="{{if .PageIsExploreCode}}active {{end}}item" href="{{AppSubUrl}}/explore/code">
{{svg "octicon-code"}} {{ctx.Locale.Tr "explore.code"}} {{svg "octicon-code"}} {{ctx.Locale.Tr "explore.code"}}
</a> </a>

View File

@ -80,7 +80,7 @@
</table> </table>
{{end}}{{/* end if .IsFileTooLarge */}} {{end}}{{/* end if .IsFileTooLarge */}}
<div class="code-line-menu tippy-target"> <div class="code-line-menu tippy-target">
{{if $.Permission.CanRead $.UnitTypeIssues}} {{if $.Permission.CanRead ctx.Consts.RepoUnitTypeIssues}}
<a class="item ref-in-new-issue" role="menuitem" data-url-issue-new="{{.RepoLink}}/issues/new" data-url-param-body-link="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}{{if $.HasSourceRenderedToggle}}?display=source{{end}}" rel="nofollow noindex">{{ctx.Locale.Tr "repo.issues.context.reference_issue"}}</a> <a class="item ref-in-new-issue" role="menuitem" data-url-issue-new="{{.RepoLink}}/issues/new" data-url-param-body-link="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}{{if $.HasSourceRenderedToggle}}?display=source{{end}}" rel="nofollow noindex">{{ctx.Locale.Tr "repo.issues.context.reference_issue"}}</a>
{{end}} {{end}}
<a class="item copy-line-permalink" role="menuitem" data-url="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}{{if $.HasSourceRenderedToggle}}?display=source{{end}}">{{ctx.Locale.Tr "repo.file_copy_permalink"}}</a> <a class="item copy-line-permalink" role="menuitem" data-url="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}{{if $.HasSourceRenderedToggle}}?display=source{{end}}">{{ctx.Locale.Tr "repo.file_copy_permalink"}}</a>

View File

@ -1,4 +1,4 @@
{{if .Permission.CanRead $.UnitTypeCode}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
<div id="repo-code-frequency-chart" <div id="repo-code-frequency-chart"
data-locale-loading-title="{{ctx.Locale.Tr "graphs.component_loading" (ctx.Locale.Tr "graphs.code_frequency.what")}}" data-locale-loading-title="{{ctx.Locale.Tr "graphs.component_loading" (ctx.Locale.Tr "graphs.code_frequency.what")}}"
data-locale-loading-title-failed="{{ctx.Locale.Tr "graphs.component_loading_failed" (ctx.Locale.Tr "graphs.code_frequency.what")}}" data-locale-loading-title-failed="{{ctx.Locale.Tr "graphs.component_loading_failed" (ctx.Locale.Tr "graphs.code_frequency.what")}}"

View File

@ -25,7 +25,7 @@
<a class="ui primary tiny button" href="{{.SourcePath}}"> <a class="ui primary tiny button" href="{{.SourcePath}}">
{{ctx.Locale.Tr "repo.diff.browse_source"}} {{ctx.Locale.Tr "repo.diff.browse_source"}}
</a> </a>
{{if and ($.Permission.CanWrite $.UnitTypeCode) (not $.Repository.IsArchived) (not .IsDeleted)}}{{- /* */ -}} {{if and ($.Permission.CanWrite ctx.Consts.RepoUnitTypeCode) (not $.Repository.IsArchived) (not .IsDeleted)}}{{- /* */ -}}
<div class="ui dropdown primary tiny button"> <div class="ui dropdown primary tiny button">
{{ctx.Locale.Tr "repo.commit.operations"}} {{ctx.Locale.Tr "repo.commit.operations"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}

View File

@ -1,4 +1,4 @@
{{if .Permission.CanRead $.UnitTypeCode}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
<div id="repo-contributors-chart" <div id="repo-contributors-chart"
data-locale-filter-label="{{ctx.Locale.Tr "repo.contributors.contribution_type.filter_label"}}" data-locale-filter-label="{{ctx.Locale.Tr "repo.contributors.contribution_type.filter_label"}}"
data-locale-contribution-type-commits="{{ctx.Locale.Tr "repo.contributors.contribution_type.commits"}}" data-locale-contribution-type-commits="{{ctx.Locale.Tr "repo.contributors.contribution_type.commits"}}"

View File

@ -37,7 +37,7 @@
{{if eq $refGroup "pull"}} {{if eq $refGroup "pull"}}
{{if or (not $.HidePRRefs) (SliceUtils.Contains $.SelectedBranches .Name)}} {{if or (not $.HidePRRefs) (SliceUtils.Contains $.SelectedBranches .Name)}}
<!-- it's intended to use issues not pulls, if it's a pull you will get redirected --> <!-- it's intended to use issues not pulls, if it's a pull you will get redirected -->
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.Context $.UnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}"> <a class="ui labelled basic tiny button" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}">
{{svg "octicon-git-pull-request"}} #{{.ShortName}} {{svg "octicon-git-pull-request"}} #{{.ShortName}}
</a> </a>
{{end}} {{end}}

View File

@ -64,7 +64,7 @@
{{if not $.DisableStars}} {{if not $.DisableStars}}
{{template "repo/star_unstar" $}} {{template "repo/star_unstar" $}}
{{end}} {{end}}
{{if and (not .IsEmpty) ($.Permission.CanRead $.UnitTypeCode)}} {{if and (not .IsEmpty) ($.Permission.CanRead ctx.Consts.RepoUnitTypeCode)}}
<div class="ui labeled button <div class="ui labeled button
{{if or (not $.IsSigned) (and (not $.CanSignedUserFork) (not $.UserAndOrgForks))}} {{if or (not $.IsSigned) (and (not $.CanSignedUserFork) (not $.UserAndOrgForks))}}
disabled disabled
@ -131,13 +131,13 @@
<overflow-menu class="ui container secondary pointing tabular top attached borderless menu tw-pt-0 tw-my-0"> <overflow-menu class="ui container secondary pointing tabular top attached borderless menu tw-pt-0 tw-my-0">
{{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}} {{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}}
<div class="overflow-menu-items"> <div class="overflow-menu-items">
{{if .Permission.CanRead $.UnitTypeCode}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
<a class="{{if .PageIsViewCode}}active {{end}}item" href="{{.RepoLink}}{{if and (ne .BranchName .Repository.DefaultBranch) (not $.PageIsWiki)}}/src/{{.BranchNameSubURL}}{{end}}"> <a class="{{if .PageIsViewCode}}active {{end}}item" href="{{.RepoLink}}{{if and (ne .BranchName .Repository.DefaultBranch) (not $.PageIsWiki)}}/src/{{.BranchNameSubURL}}{{end}}">
{{svg "octicon-code"}} {{ctx.Locale.Tr "repo.code"}} {{svg "octicon-code"}} {{ctx.Locale.Tr "repo.code"}}
</a> </a>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeIssues}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeIssues}}
<a class="{{if .PageIsIssueList}}active {{end}}item" href="{{.RepoLink}}/issues"> <a class="{{if .PageIsIssueList}}active {{end}}item" href="{{.RepoLink}}/issues">
{{svg "octicon-issue-opened"}} {{ctx.Locale.Tr "repo.issues"}} {{svg "octicon-issue-opened"}} {{ctx.Locale.Tr "repo.issues"}}
{{if .Repository.NumOpenIssues}} {{if .Repository.NumOpenIssues}}
@ -146,13 +146,13 @@
</a> </a>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeExternalTracker}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeExternalTracker}}
<a class="{{if .PageIsIssueList}}active {{end}}item" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer"> <a class="{{if .PageIsIssueList}}active {{end}}item" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer">
{{svg "octicon-link-external"}} {{ctx.Locale.Tr "repo.issues"}} {{svg "octicon-link-external"}} {{ctx.Locale.Tr "repo.issues"}}
</a> </a>
{{end}} {{end}}
{{if and .Repository.CanEnablePulls (.Permission.CanRead $.UnitTypePullRequests)}} {{if and .Repository.CanEnablePulls (.Permission.CanRead ctx.Consts.RepoUnitTypePullRequests)}}
<a class="{{if .PageIsPullList}}active {{end}}item" href="{{.RepoLink}}/pulls"> <a class="{{if .PageIsPullList}}active {{end}}item" href="{{.RepoLink}}/pulls">
{{svg "octicon-git-pull-request"}} {{ctx.Locale.Tr "repo.pulls"}} {{svg "octicon-git-pull-request"}} {{ctx.Locale.Tr "repo.pulls"}}
{{if .Repository.NumOpenPulls}} {{if .Repository.NumOpenPulls}}
@ -161,7 +161,7 @@
</a> </a>
{{end}} {{end}}
{{if and .EnableActions (not .UnitActionsGlobalDisabled) (.Permission.CanRead $.UnitTypeActions)}} {{if and .EnableActions (not .UnitActionsGlobalDisabled) (.Permission.CanRead ctx.Consts.RepoUnitTypeActions)}}
<a class="{{if .PageIsActions}}active {{end}}item" href="{{.RepoLink}}/actions"> <a class="{{if .PageIsActions}}active {{end}}item" href="{{.RepoLink}}/actions">
{{svg "octicon-play"}} {{ctx.Locale.Tr "actions.actions"}} {{svg "octicon-play"}} {{ctx.Locale.Tr "actions.actions"}}
{{if .Repository.NumOpenActionRuns}} {{if .Repository.NumOpenActionRuns}}
@ -170,14 +170,14 @@
</a> </a>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypePackages}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypePackages}}
<a href="{{.RepoLink}}/packages" class="{{if .IsPackagesPage}}active {{end}}item"> <a href="{{.RepoLink}}/packages" class="{{if .IsPackagesPage}}active {{end}}item">
{{svg "octicon-package"}} {{ctx.Locale.Tr "packages.title"}} {{svg "octicon-package"}} {{ctx.Locale.Tr "packages.title"}}
</a> </a>
{{end}} {{end}}
{{$projectsUnit := .Repository.MustGetUnit $.Context $.UnitTypeProjects}} {{$projectsUnit := .Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeProjects}}
{{if and (not .UnitProjectsGlobalDisabled) (.Permission.CanRead $.UnitTypeProjects) ($projectsUnit.ProjectsConfig.IsProjectsAllowed "repo")}} {{if and (not .UnitProjectsGlobalDisabled) (.Permission.CanRead ctx.Consts.RepoUnitTypeProjects) ($projectsUnit.ProjectsConfig.IsProjectsAllowed "repo")}}
<a href="{{.RepoLink}}/projects" class="{{if .IsProjectsPage}}active {{end}}item"> <a href="{{.RepoLink}}/projects" class="{{if .IsProjectsPage}}active {{end}}item">
{{svg "octicon-project"}} {{ctx.Locale.Tr "repo.project_board"}} {{svg "octicon-project"}} {{ctx.Locale.Tr "repo.project_board"}}
{{if .Repository.NumOpenProjects}} {{if .Repository.NumOpenProjects}}
@ -186,7 +186,7 @@
</a> </a>
{{end}} {{end}}
{{if and (.Permission.CanRead $.UnitTypeReleases) (not .IsEmptyRepo)}} {{if and (.Permission.CanRead ctx.Consts.RepoUnitTypeReleases) (not .IsEmptyRepo)}}
<a class="{{if or .PageIsReleaseList .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/releases"> <a class="{{if or .PageIsReleaseList .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/releases">
{{svg "octicon-tag"}} {{ctx.Locale.Tr "repo.releases"}} {{svg "octicon-tag"}} {{ctx.Locale.Tr "repo.releases"}}
{{if .NumReleases}} {{if .NumReleases}}
@ -195,19 +195,19 @@
</a> </a>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeWiki}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeWiki}}
<a class="{{if .PageIsWiki}}active {{end}}item" href="{{.RepoLink}}/wiki"> <a class="{{if .PageIsWiki}}active {{end}}item" href="{{.RepoLink}}/wiki">
{{svg "octicon-book"}} {{ctx.Locale.Tr "repo.wiki"}} {{svg "octicon-book"}} {{ctx.Locale.Tr "repo.wiki"}}
</a> </a>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeExternalWiki}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeExternalWiki}}
<a class="item" href="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}" target="_blank" rel="noopener noreferrer"> <a class="item" href="{{(.Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}" target="_blank" rel="noopener noreferrer">
{{svg "octicon-link-external"}} {{ctx.Locale.Tr "repo.wiki"}} {{svg "octicon-link-external"}} {{ctx.Locale.Tr "repo.wiki"}}
</a> </a>
{{end}} {{end}}
{{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (not .IsEmptyRepo)}} {{if and (.Permission.CanReadAny ctx.Consts.RepoUnitTypePullRequests ctx.Consts.RepoUnitTypeIssues ctx.Consts.RepoUnitTypeReleases) (not .IsEmptyRepo)}}
<a class="{{if .PageIsActivity}}active {{end}}item" href="{{.RepoLink}}/activity"> <a class="{{if .PageIsActivity}}active {{end}}item" href="{{.RepoLink}}/activity">
{{svg "octicon-pulse"}} {{ctx.Locale.Tr "repo.activity"}} {{svg "octicon-pulse"}} {{ctx.Locale.Tr "repo.activity"}}
</a> </a>

View File

@ -196,7 +196,7 @@
{{end}} {{end}}
{{if .AllowMerge}} {{/* user is allowed to merge */}} {{if .AllowMerge}} {{/* user is allowed to merge */}}
{{$prUnit := .Repository.MustGetUnit $.Context $.UnitTypePullRequests}} {{$prUnit := .Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypePullRequests}}
{{$approvers := (.Issue.PullRequest.GetApprovers ctx)}} {{$approvers := (.Issue.PullRequest.GetApprovers ctx)}}
{{if or $prUnit.PullRequestsConfig.AllowMerge $prUnit.PullRequestsConfig.AllowRebase $prUnit.PullRequestsConfig.AllowRebaseMerge $prUnit.PullRequestsConfig.AllowSquash $prUnit.PullRequestsConfig.AllowFastForwardOnly}} {{if or $prUnit.PullRequestsConfig.AllowMerge $prUnit.PullRequestsConfig.AllowRebase $prUnit.PullRequestsConfig.AllowRebaseMerge $prUnit.PullRequestsConfig.AllowSquash $prUnit.PullRequestsConfig.AllowFastForwardOnly}}
{{$hasPendingPullRequestMergeTip := ""}} {{$hasPendingPullRequestMergeTip := ""}}

View File

@ -18,10 +18,10 @@
</div> </div>
</h2> </h2>
{{if (or (.Permission.CanRead $.UnitTypeIssues) (.Permission.CanRead $.UnitTypePullRequests))}} {{if (or (.Permission.CanRead ctx.Consts.RepoUnitTypeIssues) (.Permission.CanRead ctx.Consts.RepoUnitTypePullRequests))}}
<h4 class="ui top attached header">{{ctx.Locale.Tr "repo.activity.overview"}}</h4> <h4 class="ui top attached header">{{ctx.Locale.Tr "repo.activity.overview"}}</h4>
<div class="ui attached segment two column grid"> <div class="ui attached segment two column grid">
{{if .Permission.CanRead $.UnitTypePullRequests}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypePullRequests}}
<div class="column"> <div class="column">
{{if gt .Activity.ActivePRCount 0}} {{if gt .Activity.ActivePRCount 0}}
<div class="stats-table"> <div class="stats-table">
@ -38,7 +38,7 @@
{{ctx.Locale.TrN .Activity.ActivePRCount "repo.activity.active_prs_count_1" "repo.activity.active_prs_count_n" .Activity.ActivePRCount}} {{ctx.Locale.TrN .Activity.ActivePRCount "repo.activity.active_prs_count_1" "repo.activity.active_prs_count_n" .Activity.ActivePRCount}}
</div> </div>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeIssues}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeIssues}}
<div class="column"> <div class="column">
{{if gt .Activity.ActiveIssueCount 0}} {{if gt .Activity.ActiveIssueCount 0}}
<div class="stats-table"> <div class="stats-table">
@ -57,7 +57,7 @@
{{end}} {{end}}
</div> </div>
<div class="ui attached segment horizontal segments"> <div class="ui attached segment horizontal segments">
{{if .Permission.CanRead $.UnitTypePullRequests}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypePullRequests}}
<a href="#merged-pull-requests" class="ui attached segment text center"> <a href="#merged-pull-requests" class="ui attached segment text center">
<span class="text purple">{{svg "octicon-git-pull-request"}}</span> <strong>{{.Activity.MergedPRCount}}</strong><br> <span class="text purple">{{svg "octicon-git-pull-request"}}</span> <strong>{{.Activity.MergedPRCount}}</strong><br>
{{ctx.Locale.TrN .Activity.MergedPRCount "repo.activity.merged_prs_count_1" "repo.activity.merged_prs_count_n"}} {{ctx.Locale.TrN .Activity.MergedPRCount "repo.activity.merged_prs_count_1" "repo.activity.merged_prs_count_n"}}
@ -67,7 +67,7 @@
{{ctx.Locale.TrN .Activity.OpenedPRCount "repo.activity.opened_prs_count_1" "repo.activity.opened_prs_count_n"}} {{ctx.Locale.TrN .Activity.OpenedPRCount "repo.activity.opened_prs_count_1" "repo.activity.opened_prs_count_n"}}
</a> </a>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeIssues}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeIssues}}
<a href="#closed-issues" class="ui attached segment text center"> <a href="#closed-issues" class="ui attached segment text center">
<span class="text red">{{svg "octicon-issue-closed"}}</span> <strong>{{.Activity.ClosedIssueCount}}</strong><br> <span class="text red">{{svg "octicon-issue-closed"}}</span> <strong>{{.Activity.ClosedIssueCount}}</strong><br>
{{ctx.Locale.TrN .Activity.ClosedIssueCount "repo.activity.closed_issues_count_1" "repo.activity.closed_issues_count_n"}} {{ctx.Locale.TrN .Activity.ClosedIssueCount "repo.activity.closed_issues_count_1" "repo.activity.closed_issues_count_n"}}
@ -80,7 +80,7 @@
</div> </div>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeCode}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
{{if eq .Activity.Code.CommitCountInAllBranches 0}} {{if eq .Activity.Code.CommitCountInAllBranches 0}}
<div class="ui center aligned segment"> <div class="ui center aligned segment">
<h4 class="ui header">{{ctx.Locale.Tr "repo.activity.no_git_activity"}}</h4> <h4 class="ui header">{{ctx.Locale.Tr "repo.activity.no_git_activity"}}</h4>

View File

@ -1,4 +1,4 @@
{{if .Permission.CanRead $.UnitTypeCode}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
<div id="repo-recent-commits-chart" <div id="repo-recent-commits-chart"
data-locale-loading-title="{{ctx.Locale.Tr "graphs.component_loading" (ctx.Locale.Tr "graphs.recent_commits.what")}}" data-locale-loading-title="{{ctx.Locale.Tr "graphs.component_loading" (ctx.Locale.Tr "graphs.recent_commits.what")}}"
data-locale-loading-title-failed="{{ctx.Locale.Tr "graphs.component_loading_failed" (ctx.Locale.Tr "graphs.recent_commits.what")}}" data-locale-loading-title-failed="{{ctx.Locale.Tr "graphs.component_loading_failed" (ctx.Locale.Tr "graphs.recent_commits.what")}}"

View File

@ -9,8 +9,8 @@
{{$release := $info.Release}} {{$release := $info.Release}}
<li class="ui grid"> <li class="ui grid">
<div class="ui four wide column meta"> <div class="ui four wide column meta">
<a class="muted" href="{{if not (and $release.Sha1 ($.Permission.CanRead $.UnitTypeCode))}}#{{else}}{{$.RepoLink}}/src/tag/{{$release.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "tw-mr-1"}}{{$release.TagName}}</a> <a class="muted" href="{{if not (and $release.Sha1 ($.Permission.CanRead ctx.Consts.RepoUnitTypeCode))}}#{{else}}{{$.RepoLink}}/src/tag/{{$release.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "tw-mr-1"}}{{$release.TagName}}</a>
{{if and $release.Sha1 ($.Permission.CanRead $.UnitTypeCode)}} {{if and $release.Sha1 ($.Permission.CanRead ctx.Consts.RepoUnitTypeCode)}}
<a class="muted tw-font-mono" href="{{$.RepoLink}}/src/commit/{{$release.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha $release.Sha1}}</a> <a class="muted tw-font-mono" href="{{$.RepoLink}}/src/commit/{{$release.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha $release.Sha1}}</a>
{{template "repo/branch_dropdown" dict "root" $ "release" $release}} {{template "repo/branch_dropdown" dict "root" $ "release" $release}}
{{end}} {{end}}
@ -53,7 +53,7 @@
{{if $release.CreatedUnix}} {{if $release.CreatedUnix}}
<span class="time">{{TimeSinceUnix $release.CreatedUnix ctx.Locale}}</span> <span class="time">{{TimeSinceUnix $release.CreatedUnix ctx.Locale}}</span>
{{end}} {{end}}
{{if and (not $release.IsDraft) ($.Permission.CanRead $.UnitTypeCode)}} {{if and (not $release.IsDraft) ($.Permission.CanRead ctx.Consts.RepoUnitTypeCode)}}
| <span class="ahead"><a href="{{$.RepoLink}}/compare/{{$release.TagName | PathEscapeSegments}}...{{$release.TargetBehind | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.release.ahead.commits" $release.NumCommitsBehind}}</a> {{ctx.Locale.Tr "repo.release.ahead.target" $release.TargetBehind}}</span> | <span class="ahead"><a href="{{$.RepoLink}}/compare/{{$release.TagName | PathEscapeSegments}}...{{$release.TargetBehind | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.release.ahead.commits" $release.NumCommitsBehind}}</a> {{ctx.Locale.Tr "repo.release.ahead.target" $release.TargetBehind}}</span>
{{end}} {{end}}
</p> </p>
@ -66,7 +66,7 @@
{{ctx.Locale.Tr "repo.release.downloads"}} {{ctx.Locale.Tr "repo.release.downloads"}}
</summary> </summary>
<ul class="list"> <ul class="list">
{{if and (not $.DisableDownloadSourceArchives) (not $release.IsDraft) ($.Permission.CanRead $.UnitTypeCode)}} {{if and (not $.DisableDownloadSourceArchives) (not $release.IsDraft) ($.Permission.CanRead ctx.Consts.RepoUnitTypeCode)}}
<li> <li>
<a class="archive-link" href="{{$.RepoLink}}/archive/{{$release.TagName | PathEscapeSegments}}.zip" rel="nofollow"><strong>{{svg "octicon-file-zip" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.source_code"}} (ZIP)</strong></a> <a class="archive-link" href="{{$.RepoLink}}/archive/{{$release.TagName | PathEscapeSegments}}.zip" rel="nofollow"><strong>{{svg "octicon-file-zip" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.source_code"}} (ZIP)</strong></a>
</li> </li>
@ -99,7 +99,7 @@
</div> </div>
</div> </div>
{{if (and ($.Permission.CanWrite $.UnitTypeCode) .PageIsTagList)}} {{if (and ($.Permission.CanWrite ctx.Consts.RepoUnitTypeCode) .PageIsTagList)}}
<div class="ui g-modal-confirm delete modal"> <div class="ui g-modal-confirm delete modal">
<div class="header"> <div class="header">
{{svg "octicon-trash"}} {{svg "octicon-trash"}}

View File

@ -1,5 +1,5 @@
{{$canReadReleases := $.Permission.CanRead $.UnitTypeReleases}} {{$canReadReleases := $.Permission.CanRead ctx.Consts.RepoUnitTypeReleases}}
{{$canReadCode := $.Permission.CanRead $.UnitTypeCode}} {{$canReadCode := $.Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
{{if $canReadReleases}} {{if $canReadReleases}}
<div class="tw-flex"> <div class="tw-flex">

View File

@ -12,7 +12,7 @@
{{ctx.Locale.Tr "repo.settings.hooks"}} {{ctx.Locale.Tr "repo.settings.hooks"}}
</a> </a>
{{end}} {{end}}
{{if .Repository.UnitEnabled $.Context $.UnitTypeCode}} {{if .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeCode}}
{{if not .Repository.IsEmpty}} {{if not .Repository.IsEmpty}}
<a class="{{if .PageIsSettingsBranches}}active {{end}}item" href="{{.RepoLink}}/settings/branches"> <a class="{{if .PageIsSettingsBranches}}active {{end}}item" href="{{.RepoLink}}/settings/branches">
{{ctx.Locale.Tr "repo.settings.branches"}} {{ctx.Locale.Tr "repo.settings.branches"}}
@ -35,7 +35,7 @@
</a> </a>
{{end}} {{end}}
{{end}} {{end}}
{{if and .EnableActions (not .UnitActionsGlobalDisabled) (.Permission.CanRead $.UnitTypeActions)}} {{if and .EnableActions (not .UnitActionsGlobalDisabled) (.Permission.CanRead ctx.Consts.RepoUnitTypeActions)}}
<details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables}}open{{end}}> <details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsSecrets .PageIsSharedSettingsVariables}}open{{end}}>
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary> <summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
<div class="menu"> <div class="menu">

View File

@ -66,7 +66,7 @@
{{/* These variables exist to make the logic in the Settings window easier to comprehend and are not used later on. */}} {{/* These variables exist to make the logic in the Settings window easier to comprehend and are not used later on. */}}
{{$newMirrorsPartiallyEnabled := or (not .DisableNewPullMirrors) (not .DisableNewPushMirrors)}} {{$newMirrorsPartiallyEnabled := or (not .DisableNewPullMirrors) (not .DisableNewPushMirrors)}}
{{/* .Repository.IsMirror is not always reliable if the repository is not actively acting as a mirror because of errors. */}} {{/* .Repository.IsMirror is not always reliable if the repository is not actively acting as a mirror because of errors. */}}
{{$showMirrorSettings := and (.Repository.UnitEnabled $.Context $.UnitTypeCode) (or $newMirrorsPartiallyEnabled .Repository.IsMirror .PullMirror .PushMirrors)}} {{$showMirrorSettings := and (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeCode) (or $newMirrorsPartiallyEnabled .Repository.IsMirror .PullMirror .PushMirrors)}}
{{$newMirrorsEntirelyEnabled := and (not .DisableNewPullMirrors) (not .DisableNewPushMirrors)}} {{$newMirrorsEntirelyEnabled := and (not .DisableNewPullMirrors) (not .DisableNewPushMirrors)}}
{{$onlyNewPushMirrorsEnabled := and (not .DisableNewPushMirrors) .DisableNewPullMirrors}} {{$onlyNewPushMirrorsEnabled := and (not .DisableNewPushMirrors) .DisableNewPullMirrors}}
{{$onlyNewPullMirrorsEnabled := and .DisableNewPushMirrors (not .DisableNewPullMirrors)}} {{$onlyNewPullMirrorsEnabled := and .DisableNewPushMirrors (not .DisableNewPullMirrors)}}
@ -307,8 +307,8 @@
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<input type="hidden" name="action" value="advanced"> <input type="hidden" name="action" value="advanced">
{{$isCodeEnabled := .Repository.UnitEnabled $.Context $.UnitTypeCode}} {{$isCodeEnabled := .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeCode}}
{{$isCodeGlobalDisabled := .UnitTypeCode.UnitGlobalDisabled}} {{$isCodeGlobalDisabled := ctx.Consts.RepoUnitTypeCode.UnitGlobalDisabled}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "repo.code"}}</label> <label>{{ctx.Locale.Tr "repo.code"}}</label>
<div class="ui checkbox{{if $isCodeGlobalDisabled}} disabled{{end}}"{{if $isCodeGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui checkbox{{if $isCodeGlobalDisabled}} disabled{{end}}"{{if $isCodeGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
@ -317,9 +317,9 @@
</div> </div>
</div> </div>
{{$isWikiEnabled := or (.Repository.UnitEnabled $.Context $.UnitTypeWiki) (.Repository.UnitEnabled $.Context $.UnitTypeExternalWiki)}} {{$isWikiEnabled := or (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeWiki) (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalWiki)}}
{{$isWikiGlobalDisabled := .UnitTypeWiki.UnitGlobalDisabled}} {{$isWikiGlobalDisabled := ctx.Consts.RepoUnitTypeWiki.UnitGlobalDisabled}}
{{$isExternalWikiGlobalDisabled := .UnitTypeExternalWiki.UnitGlobalDisabled}} {{$isExternalWikiGlobalDisabled := ctx.Consts.RepoUnitTypeExternalWiki.UnitGlobalDisabled}}
{{$isBothWikiGlobalDisabled := and $isWikiGlobalDisabled $isExternalWikiGlobalDisabled}} {{$isBothWikiGlobalDisabled := and $isWikiGlobalDisabled $isExternalWikiGlobalDisabled}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "repo.wiki"}}</label> <label>{{ctx.Locale.Tr "repo.wiki"}}</label>
@ -331,7 +331,7 @@
<div class="field{{if not $isWikiEnabled}} disabled{{end}}" id="wiki_box"> <div class="field{{if not $isWikiEnabled}} disabled{{end}}" id="wiki_box">
<div class="field"> <div class="field">
<div class="ui radio checkbox{{if $isWikiGlobalDisabled}} disabled{{end}}"{{if $isWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui radio checkbox{{if $isWikiGlobalDisabled}} disabled{{end}}"{{if $isWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
<input class="enable-system-radio" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalWiki)}}checked{{end}}> <input class="enable-system-radio" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalWiki)}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.use_internal_wiki"}}</label> <label>{{ctx.Locale.Tr "repo.settings.use_internal_wiki"}}</label>
</div> </div>
</div> </div>
@ -341,22 +341,22 @@
</div> </div>
<div class="field"> <div class="field">
<div class="ui radio checkbox{{if $isExternalWikiGlobalDisabled}} disabled{{end}}"{{if $isExternalWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui radio checkbox{{if $isExternalWikiGlobalDisabled}} disabled{{end}}"{{if $isExternalWikiGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
<input class="enable-system-radio" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.UnitEnabled $.Context $.UnitTypeExternalWiki}}checked{{end}}> <input class="enable-system-radio" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalWiki}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.use_external_wiki"}}</label> <label>{{ctx.Locale.Tr "repo.settings.use_external_wiki"}}</label>
</div> </div>
</div> </div>
<div class="field tw-pl-4 {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalWiki)}}disabled{{end}}" id="external_wiki_box"> <div class="field tw-pl-4 {{if not (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalWiki)}}disabled{{end}}" id="external_wiki_box">
<label for="external_wiki_url">{{ctx.Locale.Tr "repo.settings.external_wiki_url"}}</label> <label for="external_wiki_url">{{ctx.Locale.Tr "repo.settings.external_wiki_url"}}</label>
<input id="external_wiki_url" name="external_wiki_url" type="url" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}"> <input id="external_wiki_url" name="external_wiki_url" type="url" value="{{(.Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}">
<p class="help">{{ctx.Locale.Tr "repo.settings.external_wiki_url_desc"}}</p> <p class="help">{{ctx.Locale.Tr "repo.settings.external_wiki_url_desc"}}</p>
</div> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
{{$isIssuesEnabled := or (.Repository.UnitEnabled $.Context $.UnitTypeIssues) (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}} {{$isIssuesEnabled := or (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeIssues) (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalTracker)}}
{{$isIssuesGlobalDisabled := .UnitTypeIssues.UnitGlobalDisabled}} {{$isIssuesGlobalDisabled := ctx.Consts.RepoUnitTypeIssues.UnitGlobalDisabled}}
{{$isExternalTrackerGlobalDisabled := .UnitTypeExternalTracker.UnitGlobalDisabled}} {{$isExternalTrackerGlobalDisabled := ctx.Consts.RepoUnitTypeExternalTracker.UnitGlobalDisabled}}
{{$isIssuesAndExternalGlobalDisabled := and $isIssuesGlobalDisabled $isExternalTrackerGlobalDisabled}} {{$isIssuesAndExternalGlobalDisabled := and $isIssuesGlobalDisabled $isExternalTrackerGlobalDisabled}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "repo.issues"}}</label> <label>{{ctx.Locale.Tr "repo.issues"}}</label>
@ -368,11 +368,11 @@
<div class="field {{if not $isIssuesEnabled}}disabled{{end}}" id="issue_box"> <div class="field {{if not $isIssuesEnabled}}disabled{{end}}" id="issue_box">
<div class="field"> <div class="field">
<div class="ui radio checkbox{{if $isIssuesGlobalDisabled}} disabled{{end}}"{{if $isIssuesGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui radio checkbox{{if $isIssuesGlobalDisabled}} disabled{{end}}"{{if $isIssuesGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
<input class="enable-system-radio" name="enable_external_tracker" type="radio" value="false" data-context="#internal_issue_box" data-target="#external_issue_box" {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}}checked{{end}}> <input class="enable-system-radio" name="enable_external_tracker" type="radio" value="false" data-context="#internal_issue_box" data-target="#external_issue_box" {{if not (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalTracker)}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.use_internal_issue_tracker"}}</label> <label>{{ctx.Locale.Tr "repo.settings.use_internal_issue_tracker"}}</label>
</div> </div>
</div> </div>
<div class="field tw-pl-4 {{if (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}}disabled{{end}}" id="internal_issue_box"> <div class="field tw-pl-4 {{if (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalTracker)}}disabled{{end}}" id="internal_issue_box">
{{if .Repository.CanEnableTimetracker}} {{if .Repository.CanEnableTimetracker}}
<div class="field"> <div class="field">
<div class="ui checkbox"> <div class="ui checkbox">
@ -400,26 +400,26 @@
</div> </div>
<div class="field"> <div class="field">
<div class="ui radio checkbox{{if $isExternalTrackerGlobalDisabled}} disabled{{end}}"{{if $isExternalTrackerGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui radio checkbox{{if $isExternalTrackerGlobalDisabled}} disabled{{end}}"{{if $isExternalTrackerGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
<input class="enable-system-radio" name="enable_external_tracker" type="radio" value="true" data-context="#internal_issue_box" data-target="#external_issue_box" {{if .Repository.UnitEnabled $.Context $.UnitTypeExternalTracker}}checked{{end}}> <input class="enable-system-radio" name="enable_external_tracker" type="radio" value="true" data-context="#internal_issue_box" data-target="#external_issue_box" {{if .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalTracker}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.use_external_issue_tracker"}}</label> <label>{{ctx.Locale.Tr "repo.settings.use_external_issue_tracker"}}</label>
</div> </div>
</div> </div>
<div class="field tw-pl-4 {{if not (.Repository.UnitEnabled $.Context $.UnitTypeExternalTracker)}}disabled{{end}}" id="external_issue_box"> <div class="field tw-pl-4 {{if not (.Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeExternalTracker)}}disabled{{end}}" id="external_issue_box">
<div class="field"> <div class="field">
<label for="external_tracker_url">{{ctx.Locale.Tr "repo.settings.external_tracker_url"}}</label> <label for="external_tracker_url">{{ctx.Locale.Tr "repo.settings.external_tracker_url"}}</label>
<input id="external_tracker_url" name="external_tracker_url" type="url" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerURL}}"> <input id="external_tracker_url" name="external_tracker_url" type="url" value="{{(.Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerURL}}">
<p class="help">{{ctx.Locale.Tr "repo.settings.external_tracker_url_desc"}}</p> <p class="help">{{ctx.Locale.Tr "repo.settings.external_tracker_url_desc"}}</p>
</div> </div>
<div class="field"> <div class="field">
<label for="tracker_url_format">{{ctx.Locale.Tr "repo.settings.tracker_url_format"}}</label> <label for="tracker_url_format">{{ctx.Locale.Tr "repo.settings.tracker_url_format"}}</label>
<input id="tracker_url_format" name="tracker_url_format" type="url" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerFormat}}" placeholder="https://github.com/{user}/{repo}/issues/{index}"> <input id="tracker_url_format" name="tracker_url_format" type="url" value="{{(.Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerFormat}}" placeholder="https://github.com/{user}/{repo}/issues/{index}">
<p class="help">{{ctx.Locale.Tr "repo.settings.tracker_url_format_desc"}}</p> <p class="help">{{ctx.Locale.Tr "repo.settings.tracker_url_format_desc"}}</p>
</div> </div>
<div class="inline fields"> <div class="inline fields">
<label for="issue_style">{{ctx.Locale.Tr "repo.settings.tracker_issue_style"}}</label> <label for="issue_style">{{ctx.Locale.Tr "repo.settings.tracker_issue_style"}}</label>
<div class="field"> <div class="field">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
{{$externalTracker := (.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker)}} {{$externalTracker := (.Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeExternalTracker)}}
{{$externalTrackerStyle := $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle}} {{$externalTrackerStyle := $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle}}
<input class="js-tracker-issue-style" name="tracker_issue_style" type="radio" value="numeric" {{if eq $externalTrackerStyle "numeric"}}checked{{end}}> <input class="js-tracker-issue-style" name="tracker_issue_style" type="radio" value="numeric" {{if eq $externalTrackerStyle "numeric"}}checked{{end}}>
<label>{{ctx.Locale.Tr "repo.settings.tracker_issue_style.numeric"}} <span class="ui light grey text">#1234</span></label> <label>{{ctx.Locale.Tr "repo.settings.tracker_issue_style.numeric"}} <span class="ui light grey text">#1234</span></label>
@ -440,7 +440,7 @@
</div> </div>
<div class="field {{if ne $externalTrackerStyle "regexp"}}disabled{{end}}" id="tracker-issue-style-regex-box"> <div class="field {{if ne $externalTrackerStyle "regexp"}}disabled{{end}}" id="tracker-issue-style-regex-box">
<label for="external_tracker_regexp_pattern">{{ctx.Locale.Tr "repo.settings.tracker_issue_style.regexp_pattern"}}</label> <label for="external_tracker_regexp_pattern">{{ctx.Locale.Tr "repo.settings.tracker_issue_style.regexp_pattern"}}</label>
<input id="external_tracker_regexp_pattern" name="external_tracker_regexp_pattern" value="{{(.Repository.MustGetUnit $.Context $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerRegexpPattern}}"> <input id="external_tracker_regexp_pattern" name="external_tracker_regexp_pattern" value="{{(.Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerRegexpPattern}}">
<p class="help">{{ctx.Locale.Tr "repo.settings.tracker_issue_style.regexp_pattern_desc"}}</p> <p class="help">{{ctx.Locale.Tr "repo.settings.tracker_issue_style.regexp_pattern_desc"}}</p>
</div> </div>
</div> </div>
@ -448,9 +448,9 @@
<div class="divider"></div> <div class="divider"></div>
{{$isProjectsEnabled := .Repository.UnitEnabled $.Context $.UnitTypeProjects}} {{$isProjectsEnabled := .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeProjects}}
{{$isProjectsGlobalDisabled := .UnitTypeProjects.UnitGlobalDisabled}} {{$isProjectsGlobalDisabled := ctx.Consts.RepoUnitTypeProjects.UnitGlobalDisabled}}
{{$projectsUnit := .Repository.MustGetUnit $.Context $.UnitTypeProjects}} {{$projectsUnit := .Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypeProjects}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "repo.project_board"}}</label> <label>{{ctx.Locale.Tr "repo.project_board"}}</label>
<div class="ui checkbox{{if $isProjectsGlobalDisabled}} disabled{{end}}"{{if $isProjectsGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui checkbox{{if $isProjectsGlobalDisabled}} disabled{{end}}"{{if $isProjectsGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
@ -490,8 +490,8 @@
<div class="divider"></div> <div class="divider"></div>
{{$isReleasesEnabled := .Repository.UnitEnabled $.Context $.UnitTypeReleases}} {{$isReleasesEnabled := .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeReleases}}
{{$isReleasesGlobalDisabled := .UnitTypeReleases.UnitGlobalDisabled}} {{$isReleasesGlobalDisabled := ctx.Consts.RepoUnitTypeReleases.UnitGlobalDisabled}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "repo.releases"}}</label> <label>{{ctx.Locale.Tr "repo.releases"}}</label>
<div class="ui checkbox{{if $isReleasesGlobalDisabled}} disabled{{end}}"{{if $isReleasesGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui checkbox{{if $isReleasesGlobalDisabled}} disabled{{end}}"{{if $isReleasesGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
@ -500,8 +500,8 @@
</div> </div>
</div> </div>
{{$isPackagesEnabled := .Repository.UnitEnabled $.Context $.UnitTypePackages}} {{$isPackagesEnabled := .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypePackages}}
{{$isPackagesGlobalDisabled := .UnitTypePackages.UnitGlobalDisabled}} {{$isPackagesGlobalDisabled := ctx.Consts.RepoUnitTypePackages.UnitGlobalDisabled}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "repo.packages"}}</label> <label>{{ctx.Locale.Tr "repo.packages"}}</label>
<div class="ui checkbox{{if $isPackagesGlobalDisabled}} disabled{{end}}"{{if $isPackagesGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui checkbox{{if $isPackagesGlobalDisabled}} disabled{{end}}"{{if $isPackagesGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
@ -511,8 +511,8 @@
</div> </div>
{{if .EnableActions}} {{if .EnableActions}}
{{$isActionsEnabled := .Repository.UnitEnabled $.Context $.UnitTypeActions}} {{$isActionsEnabled := .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeActions}}
{{$isActionsGlobalDisabled := .UnitTypeActions.UnitGlobalDisabled}} {{$isActionsGlobalDisabled := ctx.Consts.RepoUnitTypeActions.UnitGlobalDisabled}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "actions.actions"}}</label> <label>{{ctx.Locale.Tr "actions.actions"}}</label>
<div class="ui checkbox{{if $isActionsGlobalDisabled}} disabled{{end}}"{{if $isActionsGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui checkbox{{if $isActionsGlobalDisabled}} disabled{{end}}"{{if $isActionsGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
@ -524,9 +524,9 @@
{{if not .IsMirror}} {{if not .IsMirror}}
<div class="divider"></div> <div class="divider"></div>
{{$pullRequestEnabled := .Repository.UnitEnabled $.Context $.UnitTypePullRequests}} {{$pullRequestEnabled := .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypePullRequests}}
{{$pullRequestGlobalDisabled := .UnitTypePullRequests.UnitGlobalDisabled}} {{$pullRequestGlobalDisabled := ctx.Consts.RepoUnitTypePullRequests.UnitGlobalDisabled}}
{{$prUnit := .Repository.MustGetUnit $.Context $.UnitTypePullRequests}} {{$prUnit := .Repository.MustGetUnit $.Context ctx.Consts.RepoUnitTypePullRequests}}
<div class="inline field"> <div class="inline field">
<label>{{ctx.Locale.Tr "repo.pulls"}}</label> <label>{{ctx.Locale.Tr "repo.pulls"}}</label>
<div class="ui checkbox{{if $pullRequestGlobalDisabled}} disabled{{end}}"{{if $pullRequestGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}> <div class="ui checkbox{{if $pullRequestGlobalDisabled}} disabled{{end}}"{{if $pullRequestGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
@ -816,7 +816,7 @@
{{end}} {{end}}
</div> </div>
</div> </div>
{{if .Permission.CanRead $.UnitTypeWiki}} {{if .Permission.CanRead ctx.Consts.RepoUnitTypeWiki}}
<div class="flex-item"> <div class="flex-item">
<div class="flex-item-main"> <div class="flex-item-main">
<div class="flex-item-title">{{ctx.Locale.Tr "repo.settings.wiki_delete"}}</div> <div class="flex-item-title">{{ctx.Locale.Tr "repo.settings.wiki_delete"}}</div>
@ -997,7 +997,7 @@
</div> </div>
</div> </div>
{{if .Repository.UnitEnabled $.Context $.UnitTypeWiki}} {{if .Repository.UnitEnabled $.Context ctx.Consts.RepoUnitTypeWiki}}
<div class="ui small modal" id="delete-wiki-modal"> <div class="ui small modal" id="delete-wiki-modal">
<div class="header"> <div class="header">
{{ctx.Locale.Tr "repo.settings.wiki_delete"}} {{ctx.Locale.Tr "repo.settings.wiki_delete"}}

View File

@ -1,14 +1,14 @@
{{if and (not .HideRepoInfo) (not .IsBlame)}} {{if and (not .HideRepoInfo) (not .IsBlame)}}
<div class="ui segments repository-summary tw-mt-1 tw-mb-0"> <div class="ui segments repository-summary tw-mt-1 tw-mb-0">
<div class="ui segment sub-menu repository-menu"> <div class="ui segment sub-menu repository-menu">
{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo)}} {{if and (.Permission.CanRead ctx.Consts.RepoUnitTypeCode) (not .IsEmptyRepo)}}
<a class="item muted {{if .PageIsCommits}}active{{end}}" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}"> <a class="item muted {{if .PageIsCommits}}active{{end}}" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}">
{{svg "octicon-history"}} <b>{{ctx.Locale.PrettyNumber .CommitsCount}}</b> {{ctx.Locale.TrN .CommitsCount "repo.commit" "repo.commits"}} {{svg "octicon-history"}} <b>{{ctx.Locale.PrettyNumber .CommitsCount}}</b> {{ctx.Locale.TrN .CommitsCount "repo.commit" "repo.commits"}}
</a> </a>
<a class="item muted {{if .PageIsBranches}}active{{end}}" href="{{.RepoLink}}/branches"> <a class="item muted {{if .PageIsBranches}}active{{end}}" href="{{.RepoLink}}/branches">
{{svg "octicon-git-branch"}} <b>{{ctx.Locale.PrettyNumber .BranchesCount}}</b> {{ctx.Locale.TrN .BranchesCount "repo.branch" "repo.branches"}} {{svg "octicon-git-branch"}} <b>{{ctx.Locale.PrettyNumber .BranchesCount}}</b> {{ctx.Locale.TrN .BranchesCount "repo.branch" "repo.branches"}}
</a> </a>
{{if $.Permission.CanRead $.UnitTypeCode}} {{if $.Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
<a class="item muted {{if .PageIsTagList}}active{{end}}" href="{{.RepoLink}}/tags"> <a class="item muted {{if .PageIsTagList}}active{{end}}" href="{{.RepoLink}}/tags">
{{svg "octicon-tag"}} <b>{{ctx.Locale.PrettyNumber .NumTags}}</b> {{ctx.Locale.TrN .NumTags "repo.tag" "repo.tags"}} {{svg "octicon-tag"}} <b>{{ctx.Locale.PrettyNumber .NumTags}}</b> {{ctx.Locale.TrN .NumTags "repo.tag" "repo.tags"}}
</a> </a>
@ -20,7 +20,7 @@
</span> </span>
{{end}} {{end}}
</div> </div>
{{if and (.Permission.CanRead $.UnitTypeCode) (not .IsEmptyRepo) .LanguageStats}} {{if and (.Permission.CanRead ctx.Consts.RepoUnitTypeCode) (not .IsEmptyRepo) .LanguageStats}}
<div class="ui segment sub-menu language-stats-details tw-hidden"> <div class="ui segment sub-menu language-stats-details tw-hidden">
{{range .LanguageStats}} {{range .LanguageStats}}
<div class="item"> <div class="item">

View File

@ -9,7 +9,7 @@
{{svg "octicon-tag" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.tags"}} {{svg "octicon-tag" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.tags"}}
</div> </div>
</h4> </h4>
{{$canReadReleases := $.Permission.CanRead $.UnitTypeReleases}} {{$canReadReleases := $.Permission.CanRead ctx.Consts.RepoUnitTypeReleases}}
<div class="ui attached table segment"> <div class="ui attached table segment">
<table class="ui very basic striped fixed table single line" id="tags-table"> <table class="ui very basic striped fixed table single line" id="tags-table">
<tbody class="tag-list"> <tbody class="tag-list">
@ -24,7 +24,7 @@
{{end}} {{end}}
</h3> </h3>
<div class="download tw-flex tw-items-center"> <div class="download tw-flex tw-items-center">
{{if $.Permission.CanRead $.UnitTypeCode}} {{if $.Permission.CanRead ctx.Consts.RepoUnitTypeCode}}
{{if .CreatedUnix}} {{if .CreatedUnix}}
<span class="tw-mr-2">{{svg "octicon-clock" 16 "tw-mr-1"}}{{TimeSinceUnix .CreatedUnix ctx.Locale}}</span> <span class="tw-mr-2">{{svg "octicon-clock" 16 "tw-mr-1"}}{{TimeSinceUnix .CreatedUnix ctx.Locale}}</span>
{{end}} {{end}}
@ -40,7 +40,7 @@
<a class="tw-mr-2 muted" href="{{$.RepoLink}}/releases/new?tag={{.TagName}}">{{svg "octicon-tag" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.new_release"}}</a> <a class="tw-mr-2 muted" href="{{$.RepoLink}}/releases/new?tag={{.TagName}}">{{svg "octicon-tag" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.new_release"}}</a>
{{end}} {{end}}
{{if (and ($.Permission.CanWrite $.UnitTypeCode) $release.IsTag)}} {{if (and ($.Permission.CanWrite ctx.Consts.RepoUnitTypeCode) $release.IsTag)}}
<a class="ui delete-button tw-mr-2 muted" data-url="{{$.RepoLink}}/tags/delete" data-id="{{.ID}}"> <a class="ui delete-button tw-mr-2 muted" data-url="{{$.RepoLink}}/tags/delete" data-id="{{.ID}}">
{{svg "octicon-trash" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.delete_tag"}} {{svg "octicon-trash" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.delete_tag"}}
</a> </a>
@ -62,7 +62,7 @@
</div> </div>
</div> </div>
{{if $.Permission.CanWrite $.UnitTypeCode}} {{if $.Permission.CanWrite ctx.Consts.RepoUnitTypeCode}}
<div class="ui g-modal-confirm delete modal"> <div class="ui g-modal-confirm delete modal">
<div class="header"> <div class="header">
{{svg "octicon-trash"}} {{svg "octicon-trash"}}

View File

@ -129,7 +129,7 @@
</tbody> </tbody>
</table> </table>
<div class="code-line-menu tippy-target"> <div class="code-line-menu tippy-target">
{{if $.Permission.CanRead $.UnitTypeIssues}} {{if $.Permission.CanRead ctx.Consts.RepoUnitTypeIssues}}
<a class="item ref-in-new-issue" role="menuitem" data-url-issue-new="{{.RepoLink}}/issues/new" data-url-param-body-link="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}{{if $.HasSourceRenderedToggle}}?display=source{{end}}" rel="nofollow noindex">{{ctx.Locale.Tr "repo.issues.context.reference_issue"}}</a> <a class="item ref-in-new-issue" role="menuitem" data-url-issue-new="{{.RepoLink}}/issues/new" data-url-param-body-link="{{.Repository.Link}}/src/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}{{if $.HasSourceRenderedToggle}}?display=source{{end}}" rel="nofollow noindex">{{ctx.Locale.Tr "repo.issues.context.reference_issue"}}</a>
{{end}} {{end}}
<a class="item view_git_blame" role="menuitem" href="{{.Repository.Link}}/blame/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{ctx.Locale.Tr "repo.view_git_blame"}}</a> <a class="item view_git_blame" role="menuitem" href="{{.Repository.Link}}/blame/commit/{{PathEscape .CommitID}}/{{PathEscapeSegments .TreePath}}">{{ctx.Locale.Tr "repo.view_git_blame"}}</a>