Merge branch 'main' into feature/bots

This commit is contained in:
Jason Song 2022-12-12 10:46:13 +08:00 committed by GitHub
commit dfa1b6168d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
119 changed files with 766 additions and 803 deletions

View File

@ -778,6 +778,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
func getReleaseCount(id int64) (int64, error) { func getReleaseCount(id int64) (int64, error) {
return repo_model.GetReleaseCountByRepoID( return repo_model.GetReleaseCountByRepoID(
db.DefaultContext,
id, id,
repo_model.FindReleasesOptions{ repo_model.FindReleasesOptions{
IncludeTags: true, IncludeTags: true,

View File

@ -2147,7 +2147,7 @@ ROUTER = console
;[cron.update_checker] ;[cron.update_checker]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ENABLED = false ;ENABLED = true
;RUN_AT_START = false ;RUN_AT_START = false
;ENABLE_SUCCESS_NOTICE = false ;ENABLE_SUCCESS_NOTICE = false
;SCHEDULE = @every 168h ;SCHEDULE = @every 168h

View File

@ -1005,7 +1005,7 @@ Default templates for project boards:
#### Cron - Check for new Gitea versions ('cron.update_checker') #### Cron - Check for new Gitea versions ('cron.update_checker')
- `ENABLED`: **false**: Enable service. - `ENABLED`: **true**: Enable service.
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED). - `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
- `ENABLE_SUCCESS_NOTICE`: **true**: Set to false to switch off success notices. - `ENABLE_SUCCESS_NOTICE`: **true**: Set to false to switch off success notices.
- `SCHEDULE`: **@every 168h**: Cron syntax for scheduling a work, e.g. `@every 168h`. - `SCHEDULE`: **@every 168h**: Cron syntax for scheduling a work, e.g. `@every 168h`.

6
go.mod
View File

@ -113,8 +113,8 @@ require (
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
mvdan.cc/xurls/v2 v2.4.0 mvdan.cc/xurls/v2 v2.4.0
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
xorm.io/builder v0.3.11 xorm.io/builder v0.3.12
xorm.io/xorm v1.3.2-0.20220714055524-c3bce556200f xorm.io/xorm v1.3.3-0.20221209153726-f1bfc5ce9830
) )
require ( require (
@ -192,7 +192,7 @@ require (
github.com/go-openapi/strfmt v0.21.3 // indirect github.com/go-openapi/strfmt v0.21.3 // indirect
github.com/go-openapi/swag v0.22.3 // indirect github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-openapi/validate v0.22.0 // indirect github.com/go-openapi/validate v0.22.0 // indirect
github.com/goccy/go-json v0.9.11 // indirect github.com/goccy/go-json v0.10.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect

12
go.sum
View File

@ -612,8 +612,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@ -2405,7 +2405,7 @@ sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs= strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY= strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/builder v0.3.11 h1:naLkJitGyYW7ZZdncsh/JW+HF4HshmvTHTyUyPwJS00= xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
xorm.io/builder v0.3.11/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.3.2-0.20220714055524-c3bce556200f h1:3NvNsM4lnttTsHpk8ODHqrwN1MCEjsO3bD/rpd8A47k= xorm.io/xorm v1.3.3-0.20221209153726-f1bfc5ce9830 h1:ohaHCvT7ocSDkTEa2/2z0BXfINYlHm/Z7IzN7MeXQlM=
xorm.io/xorm v1.3.2-0.20220714055524-c3bce556200f/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw= xorm.io/xorm v1.3.3-0.20221209153726-f1bfc5ce9830/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=

View File

@ -46,7 +46,7 @@ type Engine interface {
Incr(column string, arg ...interface{}) *xorm.Session Incr(column string, arg ...interface{}) *xorm.Session
Insert(...interface{}) (int64, error) Insert(...interface{}) (int64, error)
Iterate(interface{}, xorm.IterFunc) error Iterate(interface{}, xorm.IterFunc) error
Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *xorm.Session Join(joinOperator string, tablename, condition interface{}, args ...interface{}) *xorm.Session
SQL(interface{}, ...interface{}) *xorm.Session SQL(interface{}, ...interface{}) *xorm.Session
Where(interface{}, ...interface{}) *xorm.Session Where(interface{}, ...interface{}) *xorm.Session
Asc(colNames ...string) *xorm.Session Asc(colNames ...string) *xorm.Session

View File

@ -102,7 +102,7 @@ func toggleIssueAssignee(ctx context.Context, issue *Issue, doer *user_model.Use
AssigneeID: assigneeID, AssigneeID: assigneeID,
} }
// Comment // Comment
comment, err = CreateCommentCtx(ctx, opts) comment, err = CreateComment(ctx, opts)
if err != nil { if err != nil {
return false, nil, fmt.Errorf("createComment: %w", err) return false, nil, fmt.Errorf("createComment: %w", err)
} }

View File

@ -779,8 +779,8 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) {
return err return err
} }
// CreateCommentCtx creates comment with context // CreateComment creates comment with context
func CreateCommentCtx(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) { func CreateComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) {
e := db.GetEngine(ctx) e := db.GetEngine(ctx)
var LabelID int64 var LabelID int64
if opts.Label != nil { if opts.Label != nil {
@ -915,7 +915,7 @@ func createDeadlineComment(ctx context.Context, doer *user_model.User, issue *Is
Issue: issue, Issue: issue,
Content: content, Content: content,
} }
comment, err := CreateCommentCtx(ctx, opts) comment, err := CreateComment(ctx, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -940,7 +940,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is
Issue: issue, Issue: issue,
DependentIssueID: dependentIssue.ID, DependentIssueID: dependentIssue.ID,
} }
if _, err = CreateCommentCtx(ctx, opts); err != nil { if _, err = CreateComment(ctx, opts); err != nil {
return return
} }
@ -951,7 +951,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is
Issue: dependentIssue, Issue: dependentIssue,
DependentIssueID: issue.ID, DependentIssueID: issue.ID,
} }
_, err = CreateCommentCtx(ctx, opts) _, err = CreateComment(ctx, opts)
return err return err
} }
@ -993,55 +993,6 @@ type CreateCommentOptions struct {
Invalidated bool Invalidated bool
} }
// CreateComment creates comment of issue or commit.
func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil {
return nil, err
}
defer committer.Close()
comment, err = CreateCommentCtx(ctx, opts)
if err != nil {
return nil, err
}
if err = committer.Commit(); err != nil {
return nil, err
}
return comment, nil
}
// CreateRefComment creates a commit reference comment to issue.
func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue *Issue, content, commitSHA string) error {
if len(commitSHA) == 0 {
return fmt.Errorf("cannot create reference with empty commit SHA")
}
// Check if same reference from same commit has already existed.
has, err := db.GetEngine(db.DefaultContext).Get(&Comment{
Type: CommentTypeCommitRef,
IssueID: issue.ID,
CommitSHA: commitSHA,
})
if err != nil {
return fmt.Errorf("check reference comment: %w", err)
} else if has {
return nil
}
_, err = CreateComment(&CreateCommentOptions{
Type: CommentTypeCommitRef,
Doer: doer,
Repo: repo,
Issue: issue,
CommitSHA: commitSHA,
Content: content,
})
return err
}
// GetCommentByID returns the comment by given ID. // GetCommentByID returns the comment by given ID.
func GetCommentByID(ctx context.Context, id int64) (*Comment, error) { func GetCommentByID(ctx context.Context, id int64) (*Comment, error) {
c := new(Comment) c := new(Comment)
@ -1317,39 +1268,6 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID
return err return err
} }
// CreatePushPullComment create push code to pull base comment
func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *PullRequest, oldCommitID, newCommitID string) (comment *Comment, err error) {
if pr.HasMerged || oldCommitID == "" || newCommitID == "" {
return nil, nil
}
ops := &CreateCommentOptions{
Type: CommentTypePullRequestPush,
Doer: pusher,
Repo: pr.BaseRepo,
}
var data PushActionContent
data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch)
if err != nil {
return nil, err
}
ops.Issue = pr.Issue
dataJSON, err := json.Marshal(data)
if err != nil {
return nil, err
}
ops.Content = string(dataJSON)
comment, err = CreateComment(ops)
return comment, err
}
// CreateAutoMergeComment is a internal function, only use it for CommentTypePRScheduledToAutoMerge and CommentTypePRUnScheduledToAutoMerge CommentTypes // CreateAutoMergeComment is a internal function, only use it for CommentTypePRScheduledToAutoMerge and CommentTypePRUnScheduledToAutoMerge CommentTypes
func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullRequest, doer *user_model.User) (comment *Comment, err error) { func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullRequest, doer *user_model.User) (comment *Comment, err error) {
if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge { if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge {
@ -1363,7 +1281,7 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques
return return
} }
comment, err = CreateCommentCtx(ctx, &CreateCommentOptions{ comment, err = CreateComment(ctx, &CreateCommentOptions{
Type: typ, Type: typ,
Doer: doer, Doer: doer,
Repo: pr.BaseRepo, Repo: pr.BaseRepo,
@ -1372,120 +1290,6 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques
return comment, err return comment, err
} }
// getCommitsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
// isForcePush will be true if oldCommit isn't on the branch
// Commit on baseBranch will skip
func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) {
repoPath := repo.RepoPath()
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath)
if err != nil {
return nil, false, err
}
defer closer.Close()
oldCommit, err := gitRepo.GetCommit(oldCommitID)
if err != nil {
return nil, false, err
}
if err = oldCommit.LoadBranchName(); err != nil {
return nil, false, err
}
if len(oldCommit.Branch) == 0 {
commitIDs = make([]string, 2)
commitIDs[0] = oldCommitID
commitIDs[1] = newCommitID
return commitIDs, true, err
}
newCommit, err := gitRepo.GetCommit(newCommitID)
if err != nil {
return nil, false, err
}
commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
if err != nil {
return nil, false, err
}
commitIDs = make([]string, 0, len(commits))
commitChecks := make(map[string]*commitBranchCheckItem)
for _, commit := range commits {
commitChecks[commit.ID.String()] = &commitBranchCheckItem{
Commit: commit,
Checked: false,
}
}
if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
return
}
for i := len(commits) - 1; i >= 0; i-- {
commitID := commits[i].ID.String()
if item, ok := commitChecks[commitID]; ok && item.Checked {
commitIDs = append(commitIDs, commitID)
}
}
return commitIDs, isForcePush, err
}
type commitBranchCheckItem struct {
Commit *git.Commit
Checked bool
}
func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
if startCommit.ID.String() == endCommitID {
return nil
}
checkStack := make([]string, 0, 10)
checkStack = append(checkStack, startCommit.ID.String())
for len(checkStack) > 0 {
commitID := checkStack[0]
checkStack = checkStack[1:]
item, ok := commitList[commitID]
if !ok {
continue
}
if item.Commit.ID.String() == endCommitID {
continue
}
if err := item.Commit.LoadBranchName(); err != nil {
return err
}
if item.Commit.Branch == baseBranch {
continue
}
if item.Checked {
continue
}
item.Checked = true
parentNum := item.Commit.ParentCount()
for i := 0; i < parentNum; i++ {
parentCommit, err := item.Commit.Parent(i)
if err != nil {
return err
}
checkStack = append(checkStack, parentCommit.ID.String())
}
}
return nil
}
// RemapExternalUser ExternalUserRemappable interface // RemapExternalUser ExternalUserRemappable interface
func (c *Comment) RemapExternalUser(externalName string, externalID, userID int64) error { func (c *Comment) RemapExternalUser(externalName string, externalID, userID int64) error {
c.OriginalAuthor = externalName c.OriginalAuthor = externalName

View File

@ -24,7 +24,7 @@ func TestCreateComment(t *testing.T) {
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
now := time.Now().Unix() now := time.Now().Unix()
comment, err := issues_model.CreateComment(&issues_model.CreateCommentOptions{ comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{
Type: issues_model.CommentTypeComment, Type: issues_model.CommentTypeComment,
Doer: doer, Doer: doer,
Repo: repo, Repo: repo,

View File

@ -202,16 +202,12 @@ func (issue *Issue) LoadRepo(ctx context.Context) (err error) {
} }
// IsTimetrackerEnabled returns true if the repo enables timetracking // IsTimetrackerEnabled returns true if the repo enables timetracking
func (issue *Issue) IsTimetrackerEnabled() bool { func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool {
return issue.isTimetrackerEnabled(db.DefaultContext)
}
func (issue *Issue) isTimetrackerEnabled(ctx context.Context) bool {
if err := issue.LoadRepo(ctx); err != nil { if err := issue.LoadRepo(ctx); err != nil {
log.Error(fmt.Sprintf("loadRepo: %v", err)) log.Error(fmt.Sprintf("loadRepo: %v", err))
return false return false
} }
return issue.Repo.IsTimetrackerEnabledCtx(ctx) return issue.Repo.IsTimetrackerEnabled(ctx)
} }
// GetPullRequest returns the issue pull request // GetPullRequest returns the issue pull request
@ -404,7 +400,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
if err = CommentList(issue.Comments).loadAttributes(ctx); err != nil { if err = CommentList(issue.Comments).loadAttributes(ctx); err != nil {
return err return err
} }
if issue.isTimetrackerEnabled(ctx) { if issue.IsTimetrackerEnabled(ctx) {
if err = issue.LoadTotalTimes(ctx); err != nil { if err = issue.LoadTotalTimes(ctx); err != nil {
return err return err
} }
@ -673,7 +669,7 @@ func changeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User,
func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User, isMergePull bool) (*Comment, error) { func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User, isMergePull bool) (*Comment, error) {
// Check for open dependencies // Check for open dependencies
if issue.IsClosed && issue.Repo.IsDependenciesEnabledCtx(ctx) { if issue.IsClosed && issue.Repo.IsDependenciesEnabled(ctx) {
// only check if dependencies are enabled and we're about to close an issue, otherwise reopening an issue would fail when there are unsatisfied dependencies // only check if dependencies are enabled and we're about to close an issue, otherwise reopening an issue would fail when there are unsatisfied dependencies
noDeps, err := IssueNoDependenciesLeft(ctx, issue) noDeps, err := IssueNoDependenciesLeft(ctx, issue)
if err != nil { if err != nil {
@ -725,7 +721,7 @@ func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.Use
cmtType = CommentTypeMergePull cmtType = CommentTypeMergePull
} }
return CreateCommentCtx(ctx, &CreateCommentOptions{ return CreateComment(ctx, &CreateCommentOptions{
Type: cmtType, Type: cmtType,
Doer: doer, Doer: doer,
Repo: issue.Repo, Repo: issue.Repo,
@ -769,7 +765,7 @@ func ChangeIssueTitle(issue *Issue, doer *user_model.User, oldTitle string) (err
OldTitle: oldTitle, OldTitle: oldTitle,
NewTitle: issue.Title, NewTitle: issue.Title,
} }
if _, err = CreateCommentCtx(ctx, opts); err != nil { if _, err = CreateComment(ctx, opts); err != nil {
return fmt.Errorf("createComment: %w", err) return fmt.Errorf("createComment: %w", err)
} }
if err = issue.AddCrossReferences(ctx, doer, true); err != nil { if err = issue.AddCrossReferences(ctx, doer, true); err != nil {
@ -805,7 +801,7 @@ func ChangeIssueRef(issue *Issue, doer *user_model.User, oldRef string) (err err
OldRef: oldRefFriendly, OldRef: oldRefFriendly,
NewRef: newRefFriendly, NewRef: newRefFriendly,
} }
if _, err = CreateCommentCtx(ctx, opts); err != nil { if _, err = CreateComment(ctx, opts); err != nil {
return fmt.Errorf("createComment: %w", err) return fmt.Errorf("createComment: %w", err)
} }
@ -825,7 +821,7 @@ func AddDeletePRBranchComment(ctx context.Context, doer *user_model.User, repo *
Issue: issue, Issue: issue,
OldRef: branchName, OldRef: branchName,
} }
_, err = CreateCommentCtx(ctx, opts) _, err = CreateComment(ctx, opts)
return err return err
} }
@ -992,7 +988,7 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue
OldMilestoneID: 0, OldMilestoneID: 0,
MilestoneID: opts.Issue.MilestoneID, MilestoneID: opts.Issue.MilestoneID,
} }
if _, err = CreateCommentCtx(ctx, opts); err != nil { if _, err = CreateComment(ctx, opts); err != nil {
return err return err
} }
} }
@ -2000,7 +1996,7 @@ func UpdateIssueByAPI(issue *Issue, doer *user_model.User) (statusChangeComment
OldTitle: currentIssue.Title, OldTitle: currentIssue.Title,
NewTitle: issue.Title, NewTitle: issue.Title,
} }
_, err := CreateCommentCtx(ctx, opts) _, err := CreateComment(ctx, opts)
if err != nil { if err != nil {
return nil, false, fmt.Errorf("createComment: %w", err) return nil, false, fmt.Errorf("createComment: %w", err)
} }

View File

@ -471,7 +471,7 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) {
ids := make([]int64, 0, len(issues)) ids := make([]int64, 0, len(issues))
for _, issue := range issues { for _, issue := range issues {
if issue.Repo.IsTimetrackerEnabled() { if issue.Repo.IsTimetrackerEnabled(ctx) {
ids = append(ids, issue.ID) ids = append(ids, issue.ID)
} }
} }

View File

@ -56,7 +56,7 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error {
Type: commentType, Type: commentType,
Content: opts.Reason, Content: opts.Reason,
} }
if _, err := CreateCommentCtx(ctx, opt); err != nil { if _, err := CreateComment(ctx, opt); err != nil {
return err return err
} }

View File

@ -145,7 +145,7 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U
} }
if oldProjectID > 0 || newProjectID > 0 { if oldProjectID > 0 || newProjectID > 0 {
if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Type: CommentTypeProject, Type: CommentTypeProject,
Doer: doer, Doer: doer,
Repo: issue.Repo, Repo: issue.Repo,

View File

@ -121,7 +121,7 @@ func (issue *Issue) createCrossReferences(stdCtx context.Context, ctx *crossRefe
RefAction: xref.Action, RefAction: xref.Action,
RefIsPull: ctx.OrigIssue.IsPull, RefIsPull: ctx.OrigIssue.IsPull,
} }
_, err := CreateCommentCtx(stdCtx, opts) _, err := CreateComment(stdCtx, opts)
if err != nil { if err != nil {
return err return err
} }

View File

@ -613,7 +613,7 @@ func newIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m
Label: label, Label: label,
Content: "1", Content: "1",
} }
if _, err = CreateCommentCtx(ctx, opts); err != nil { if _, err = CreateComment(ctx, opts); err != nil {
return err return err
} }
@ -714,7 +714,7 @@ func deleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use
Issue: issue, Issue: issue,
Label: label, Label: label,
} }
if _, err = CreateCommentCtx(ctx, opts); err != nil { if _, err = CreateComment(ctx, opts); err != nil {
return err return err
} }

View File

@ -294,7 +294,7 @@ func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organizatio
} }
if !pr.ProtectedBranch.EnableApprovalsWhitelist { if !pr.ProtectedBranch.EnableApprovalsWhitelist {
return team.UnitAccessModeCtx(ctx, unit.TypeCode) >= perm.AccessModeWrite, nil return team.UnitAccessMode(ctx, unit.TypeCode) >= perm.AccessModeWrite, nil
} }
return base.Int64sContains(pr.ProtectedBranch.ApprovalsWhitelistTeamIDs, team.ID), nil return base.Int64sContains(pr.ProtectedBranch.ApprovalsWhitelistTeamIDs, team.ID), nil
@ -436,7 +436,7 @@ func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, co
} }
} }
comm, err := CreateCommentCtx(ctx, &CreateCommentOptions{ comm, err := CreateComment(ctx, &CreateCommentOptions{
Type: CommentTypeReview, Type: CommentTypeReview,
Doer: doer, Doer: doer,
Content: review.Content, Content: review.Content,
@ -692,7 +692,7 @@ func AddReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment,
return nil, err return nil, err
} }
comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ comment, err := CreateComment(ctx, &CreateCommentOptions{
Type: CommentTypeReviewRequest, Type: CommentTypeReviewRequest,
Doer: doer, Doer: doer,
Repo: issue.Repo, Repo: issue.Repo,
@ -746,7 +746,7 @@ func RemoveReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Commen
} }
} }
comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ comment, err := CreateComment(ctx, &CreateCommentOptions{
Type: CommentTypeReviewRequest, Type: CommentTypeReviewRequest,
Doer: doer, Doer: doer,
Repo: issue.Repo, Repo: issue.Repo,
@ -804,7 +804,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_
} }
} }
comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ comment, err := CreateComment(ctx, &CreateCommentOptions{
Type: CommentTypeReviewRequest, Type: CommentTypeReviewRequest,
Doer: doer, Doer: doer,
Repo: issue.Repo, Repo: issue.Repo,
@ -814,7 +814,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_
ReviewID: review.ID, ReviewID: review.ID,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("CreateCommentCtx(): %w", err) return nil, fmt.Errorf("CreateComment(): %w", err)
} }
return comment, committer.Commit() return comment, committer.Commit()
@ -864,7 +864,7 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *us
return nil, committer.Commit() return nil, committer.Commit()
} }
comment, err := CreateCommentCtx(ctx, &CreateCommentOptions{ comment, err := CreateComment(ctx, &CreateCommentOptions{
Type: CommentTypeReviewRequest, Type: CommentTypeReviewRequest,
Doer: doer, Doer: doer,
Repo: issue.Repo, Repo: issue.Repo,
@ -873,7 +873,7 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *us
AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID AssigneeTeamID: reviewer.ID, // Use AssigneeTeamID as reviewer team ID
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("CreateCommentCtx(): %w", err) return nil, fmt.Errorf("CreateComment(): %w", err)
} }
return comment, committer.Commit() return comment, committer.Commit()

View File

@ -196,7 +196,7 @@ func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
return err return err
} }
if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Doer: user, Doer: user,
Issue: issue, Issue: issue,
Repo: issue.Repo, Repo: issue.Repo,
@ -246,7 +246,7 @@ func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
return err return err
} }
if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Doer: user, Doer: user,
Issue: issue, Issue: issue,
Repo: issue.Repo, Repo: issue.Repo,
@ -287,7 +287,7 @@ func cancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) e
return err return err
} }
if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Doer: user, Doer: user,
Issue: issue, Issue: issue,
Repo: issue.Repo, Repo: issue.Repo,

View File

@ -172,7 +172,7 @@ func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Tim
return nil, err return nil, err
} }
if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Issue: issue, Issue: issue,
Repo: issue.Repo, Repo: issue.Repo,
Doer: user, Doer: user,
@ -250,7 +250,7 @@ func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error {
if err := issue.LoadRepo(ctx); err != nil { if err := issue.LoadRepo(ctx); err != nil {
return err return err
} }
if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Issue: issue, Issue: issue,
Repo: issue.Repo, Repo: issue.Repo,
Doer: user, Doer: user,
@ -279,7 +279,7 @@ func DeleteTime(t *TrackedTime) error {
return err return err
} }
if _, err := CreateCommentCtx(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Issue: t.Issue, Issue: t.Issue,
Repo: t.Issue.Repo, Repo: t.Issue.Repo,
Doer: t.User, Doer: t.User,

View File

@ -106,7 +106,7 @@ func (org *Organization) IsOrgMember(uid int64) (bool, error) {
// CanCreateOrgRepo returns true if given user can create repo in organization // CanCreateOrgRepo returns true if given user can create repo in organization
func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) { func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) {
return CanCreateOrgRepo(org.ID, uid) return CanCreateOrgRepo(db.DefaultContext, org.ID, uid)
} }
func (org *Organization) getTeam(ctx context.Context, name string) (*Team, error) { func (org *Organization) getTeam(ctx context.Context, name string) (*Team, error) {

View File

@ -73,8 +73,8 @@ func IsPublicMembership(orgID, uid int64) (bool, error) {
} }
// CanCreateOrgRepo returns true if user can create repo in organization // CanCreateOrgRepo returns true if user can create repo in organization
func CanCreateOrgRepo(orgID, uid int64) (bool, error) { func CanCreateOrgRepo(ctx context.Context, orgID, uid int64) (bool, error) {
return db.GetEngine(db.DefaultContext). return db.GetEngine(ctx).
Where(builder.Eq{"team.can_create_org_repo": true}). Where(builder.Eq{"team.can_create_org_repo": true}).
Join("INNER", "team_user", "team_user.team_id = team.id"). Join("INNER", "team_user", "team_user.team_id = team.id").
And("team_user.uid = ?", uid). And("team_user.uid = ?", uid).

View File

@ -242,18 +242,12 @@ func (t *Team) LoadMembers(ctx context.Context) (err error) {
} }
// UnitEnabled returns if the team has the given unit type enabled // UnitEnabled returns if the team has the given unit type enabled
func (t *Team) UnitEnabled(tp unit.Type) bool { func (t *Team) UnitEnabled(ctx context.Context, tp unit.Type) bool {
return t.UnitAccessMode(tp) > perm.AccessModeNone return t.UnitAccessMode(ctx, tp) > perm.AccessModeNone
} }
// UnitAccessMode returns if the team has the given unit type enabled // UnitAccessMode returns if the team has the given unit type enabled
// it is called in templates, should not be replaced by `UnitAccessModeCtx(ctx ...)` func (t *Team) UnitAccessMode(ctx context.Context, tp unit.Type) perm.AccessMode {
func (t *Team) UnitAccessMode(tp unit.Type) perm.AccessMode { // Notice: It will be used in template, don't remove it directly
return t.UnitAccessModeCtx(db.DefaultContext, tp)
}
// UnitAccessModeCtx returns if the team has the given unit type enabled
func (t *Team) UnitAccessModeCtx(ctx context.Context, tp unit.Type) perm.AccessMode {
if err := t.getUnits(ctx); err != nil { if err := t.getUnits(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())
} }

View File

@ -244,7 +244,7 @@ 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.UnitAccessModeCtx(ctx, u.Type) teamMode := team.UnitAccessMode(ctx, u.Type)
if teamMode > perm_model.AccessModeNone { if teamMode > perm_model.AccessModeNone {
m := perm.UnitsMode[u.Type] m := perm.UnitsMode[u.Type]
if m < teamMode { if m < teamMode {

View File

@ -298,23 +298,10 @@ func changeProjectStatus(ctx context.Context, p *Project, isClosed bool) error {
return updateRepositoryProjectCount(ctx, p.RepoID) return updateRepositoryProjectCount(ctx, p.RepoID)
} }
// DeleteProjectByID deletes a project from a repository. // DeleteProjectByID deletes a project from a repository. if it's not in a database
func DeleteProjectByID(id int64) error { // transaction, it will start a new database transaction
ctx, committer, err := db.TxContext(db.DefaultContext) func DeleteProjectByID(ctx context.Context, id int64) error {
if err != nil { return db.AutoTx(ctx, func(ctx context.Context) error {
return err
}
defer committer.Close()
if err := DeleteProjectByIDCtx(ctx, id); err != nil {
return err
}
return committer.Commit()
}
// DeleteProjectByIDCtx deletes a project from a repository.
func DeleteProjectByIDCtx(ctx context.Context, id int64) error {
p, err := GetProjectByID(ctx, id) p, err := GetProjectByID(ctx, id)
if err != nil { if err != nil {
if IsErrProjectNotExist(err) { if IsErrProjectNotExist(err) {
@ -336,6 +323,7 @@ func DeleteProjectByIDCtx(ctx context.Context, id int64) error {
} }
return updateRepositoryProjectCount(ctx, p.RepoID) return updateRepositoryProjectCount(ctx, p.RepoID)
})
} }
func DeleteProjectByRepoID(ctx context.Context, repoID int64) error { func DeleteProjectByRepoID(ctx context.Context, repoID int64) error {

View File

@ -99,12 +99,13 @@ func getCollaborations(ctx context.Context, repoID int64, listOptions db.ListOpt
} }
// ChangeCollaborationAccessMode sets new access mode for the collaboration. // ChangeCollaborationAccessMode sets new access mode for the collaboration.
func ChangeCollaborationAccessModeCtx(ctx context.Context, repo *Repository, uid int64, mode perm.AccessMode) error { func ChangeCollaborationAccessMode(ctx context.Context, repo *Repository, uid int64, mode perm.AccessMode) error {
// Discard invalid input // Discard invalid input
if mode <= perm.AccessModeNone || mode > perm.AccessModeOwner { if mode <= perm.AccessModeNone || mode > perm.AccessModeOwner {
return nil return nil
} }
return db.AutoTx(ctx, func(ctx context.Context) error {
e := db.GetEngine(ctx) e := db.GetEngine(ctx)
collaboration := &Collaboration{ collaboration := &Collaboration{
@ -133,21 +134,7 @@ func ChangeCollaborationAccessModeCtx(ctx context.Context, repo *Repository, uid
} }
return nil return nil
} })
// ChangeCollaborationAccessMode sets new access mode for the collaboration.
func ChangeCollaborationAccessMode(repo *Repository, uid int64, mode perm.AccessMode) error {
ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil {
return err
}
defer committer.Close()
if err := ChangeCollaborationAccessModeCtx(ctx, repo, uid, mode); err != nil {
return err
}
return committer.Commit()
} }
// IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository // IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository

View File

@ -54,7 +54,7 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin))
collaboration := unittest.AssertExistsAndLoadBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4}) collaboration := unittest.AssertExistsAndLoadBean(t, &repo_model.Collaboration{RepoID: repo.ID, UserID: 4})
assert.EqualValues(t, perm.AccessModeAdmin, collaboration.Mode) assert.EqualValues(t, perm.AccessModeAdmin, collaboration.Mode)
@ -62,9 +62,9 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: repo.ID}) access := unittest.AssertExistsAndLoadBean(t, &access_model.Access{UserID: 4, RepoID: repo.ID})
assert.EqualValues(t, perm.AccessModeAdmin, access.Mode) assert.EqualValues(t, perm.AccessModeAdmin, access.Mode)
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, 4, perm.AccessModeAdmin)) assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessModeAdmin))
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, unittest.NonexistentID, perm.AccessModeAdmin)) assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin))
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID}) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
} }

View File

@ -6,7 +6,6 @@ package repo
import ( import (
"context" "context"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -26,44 +25,34 @@ func (repo *Repository) CanEnableTimetracker() bool {
} }
// IsTimetrackerEnabled returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs. // IsTimetrackerEnabled returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs.
func (repo *Repository) IsTimetrackerEnabled() bool { // Notice: It will be used in template so don't remove directly func (repo *Repository) IsTimetrackerEnabled(ctx context.Context) bool {
return repo.IsTimetrackerEnabledCtx(db.DefaultContext)
}
// IsTimetrackerEnabledCtx returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs.
func (repo *Repository) IsTimetrackerEnabledCtx(ctx context.Context) bool {
if !setting.Service.EnableTimetracking { if !setting.Service.EnableTimetracking {
return false return false
} }
var u *RepoUnit var u *RepoUnit
var err error var err error
if u, err = repo.GetUnitCtx(ctx, unit.TypeIssues); err != nil { if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil {
return setting.Service.DefaultEnableTimetracking return setting.Service.DefaultEnableTimetracking
} }
return u.IssuesConfig().EnableTimetracker return u.IssuesConfig().EnableTimetracker
} }
// AllowOnlyContributorsToTrackTime returns value of IssuesConfig or the default value // AllowOnlyContributorsToTrackTime returns value of IssuesConfig or the default value
func (repo *Repository) AllowOnlyContributorsToTrackTime() bool { func (repo *Repository) AllowOnlyContributorsToTrackTime(ctx context.Context) bool {
var u *RepoUnit var u *RepoUnit
var err error var err error
if u, err = repo.GetUnit(unit.TypeIssues); err != nil { if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil {
return setting.Service.DefaultAllowOnlyContributorsToTrackTime return setting.Service.DefaultAllowOnlyContributorsToTrackTime
} }
return u.IssuesConfig().AllowOnlyContributorsToTrackTime return u.IssuesConfig().AllowOnlyContributorsToTrackTime
} }
// IsDependenciesEnabled returns if dependencies are enabled and returns the default setting if not set. // IsDependenciesEnabled returns if dependencies are enabled and returns the default setting if not set.
func (repo *Repository) IsDependenciesEnabled() bool { func (repo *Repository) IsDependenciesEnabled(ctx context.Context) bool {
return repo.IsDependenciesEnabledCtx(db.DefaultContext)
}
// IsDependenciesEnabledCtx returns if dependencies are enabled and returns the default setting if not set.
func (repo *Repository) IsDependenciesEnabledCtx(ctx context.Context) bool {
var u *RepoUnit var u *RepoUnit
var err error var err error
if u, err = repo.GetUnitCtx(ctx, unit.TypeIssues); err != nil { if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil {
log.Trace("%s", err) log.Trace("%s", err)
return setting.Service.DefaultEnableDependencies return setting.Service.DefaultEnableDependencies
} }

View File

@ -286,8 +286,8 @@ func GetReleasesByRepoIDAndNames(ctx context.Context, repoID int64, tagNames []s
} }
// GetReleaseCountByRepoID returns the count of releases of repository // GetReleaseCountByRepoID returns the count of releases of repository
func GetReleaseCountByRepoID(repoID int64, opts FindReleasesOptions) (int64, error) { func GetReleaseCountByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) (int64, error) {
return db.GetEngine(db.DefaultContext).Where(opts.toConds(repoID)).Count(&Release{}) return db.GetEngine(ctx).Where(opts.toConds(repoID)).Count(&Release{})
} }
type releaseMetaSearch struct { type releaseMetaSearch struct {

View File

@ -319,12 +319,7 @@ func (repo *Repository) LoadUnits(ctx context.Context) (err error) {
} }
// UnitEnabled if this repository has the given unit enabled // UnitEnabled if this repository has the given unit enabled
func (repo *Repository) UnitEnabled(tp unit.Type) (result bool) { // Notice: Don't remove this function directly, because it has been used in go template. func (repo *Repository) UnitEnabled(ctx context.Context, tp unit.Type) bool {
return repo.UnitEnabledCtx(db.DefaultContext, tp)
}
// UnitEnabled if this repository has the given unit enabled
func (repo *Repository) UnitEnabledCtx(ctx context.Context, tp unit.Type) bool {
if err := repo.LoadUnits(ctx); err != nil { if err := repo.LoadUnits(ctx); err != nil {
log.Warn("Error loading repository (ID: %d) units: %s", repo.ID, err.Error()) log.Warn("Error loading repository (ID: %d) units: %s", repo.ID, err.Error())
} }
@ -337,8 +332,8 @@ func (repo *Repository) UnitEnabledCtx(ctx context.Context, tp unit.Type) bool {
} }
// MustGetUnit always returns a RepoUnit object // MustGetUnit always returns a RepoUnit object
func (repo *Repository) MustGetUnit(tp unit.Type) *RepoUnit { func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit {
ru, err := repo.GetUnit(tp) ru, err := repo.GetUnit(ctx, tp)
if err == nil { if err == nil {
return ru return ru
} }
@ -371,12 +366,7 @@ func (repo *Repository) MustGetUnit(tp unit.Type) *RepoUnit {
} }
// GetUnit returns a RepoUnit object // GetUnit returns a RepoUnit object
func (repo *Repository) GetUnit(tp unit.Type) (*RepoUnit, error) { func (repo *Repository) GetUnit(ctx context.Context, tp unit.Type) (*RepoUnit, error) {
return repo.GetUnitCtx(db.DefaultContext, tp)
}
// GetUnitCtx returns a RepoUnit object
func (repo *Repository) GetUnitCtx(ctx context.Context, tp unit.Type) (*RepoUnit, error) {
if err := repo.LoadUnits(ctx); err != nil { if err := repo.LoadUnits(ctx); err != nil {
return nil, err return nil, err
} }
@ -423,7 +413,7 @@ func (repo *Repository) ComposeMetas() map[string]string {
"mode": "comment", "mode": "comment",
} }
unit, err := repo.GetUnit(unit.TypeExternalTracker) unit, err := repo.GetUnit(db.DefaultContext, unit.TypeExternalTracker)
if err == nil { if err == nil {
metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat
switch unit.ExternalTrackerConfig().ExternalTrackerStyle { switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
@ -522,7 +512,7 @@ func (repo *Repository) CanEnablePulls() bool {
// AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled. // AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
func (repo *Repository) AllowsPulls() bool { func (repo *Repository) AllowsPulls() bool {
return repo.CanEnablePulls() && repo.UnitEnabled(unit.TypePullRequests) return repo.CanEnablePulls() && repo.UnitEnabled(db.DefaultContext, unit.TypePullRequests)
} }
// CanEnableEditor returns true if repository meets the requirements of web editor. // CanEnableEditor returns true if repository meets the requirements of web editor.

View File

@ -39,9 +39,9 @@ func init() {
} }
// LoadAttributes fetches the transfer recipient from the database // LoadAttributes fetches the transfer recipient from the database
func (r *RepoTransfer) LoadAttributes() error { func (r *RepoTransfer) LoadAttributes(ctx context.Context) error {
if r.Recipient == nil { if r.Recipient == nil {
u, err := user_model.GetUserByID(db.DefaultContext, r.RecipientID) u, err := user_model.GetUserByID(ctx, r.RecipientID)
if err != nil { if err != nil {
return err return err
} }
@ -51,7 +51,7 @@ func (r *RepoTransfer) LoadAttributes() error {
if r.Recipient.IsOrganization() && len(r.TeamIDs) != len(r.Teams) { if r.Recipient.IsOrganization() && len(r.TeamIDs) != len(r.Teams) {
for _, v := range r.TeamIDs { for _, v := range r.TeamIDs {
team, err := organization.GetTeamByID(db.DefaultContext, v) team, err := organization.GetTeamByID(ctx, v)
if err != nil { if err != nil {
return err return err
} }
@ -65,7 +65,7 @@ func (r *RepoTransfer) LoadAttributes() error {
} }
if r.Doer == nil { if r.Doer == nil {
u, err := user_model.GetUserByID(db.DefaultContext, r.DoerID) u, err := user_model.GetUserByID(ctx, r.DoerID)
if err != nil { if err != nil {
return err return err
} }
@ -80,7 +80,7 @@ func (r *RepoTransfer) LoadAttributes() error {
// For user, it checks if it's himself // For user, it checks if it's himself
// For organizations, it checks if the user is able to create repos // For organizations, it checks if the user is able to create repos
func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool { func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool {
if err := r.LoadAttributes(); err != nil { if err := r.LoadAttributes(db.DefaultContext); err != nil {
log.Error("LoadAttributes: %v", err) log.Error("LoadAttributes: %v", err)
return false return false
} }
@ -89,7 +89,7 @@ func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool {
return r.RecipientID == u.ID return r.RecipientID == u.ID
} }
allowed, err := organization.CanCreateOrgRepo(r.RecipientID, u.ID) allowed, err := organization.CanCreateOrgRepo(db.DefaultContext, r.RecipientID, u.ID)
if err != nil { if err != nil {
log.Error("CanCreateOrgRepo: %v", err) log.Error("CanCreateOrgRepo: %v", err)
return false return false
@ -100,10 +100,10 @@ func (r *RepoTransfer) CanUserAcceptTransfer(u *user_model.User) bool {
// GetPendingRepositoryTransfer fetches the most recent and ongoing transfer // GetPendingRepositoryTransfer fetches the most recent and ongoing transfer
// process for the repository // process for the repository
func GetPendingRepositoryTransfer(repo *repo_model.Repository) (*RepoTransfer, error) { func GetPendingRepositoryTransfer(ctx context.Context, repo *repo_model.Repository) (*RepoTransfer, error) {
transfer := new(RepoTransfer) transfer := new(RepoTransfer)
has, err := db.GetEngine(db.DefaultContext).Where("repo_id = ? ", repo.ID).Get(transfer) has, err := db.GetEngine(ctx).Where("repo_id = ? ", repo.ID).Get(transfer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -154,13 +154,8 @@ func TestRepositoryReadyForTransfer(status repo_model.RepositoryStatus) error {
// CreatePendingRepositoryTransfer transfer a repo from one owner to a new one. // CreatePendingRepositoryTransfer transfer a repo from one owner to a new one.
// it marks the repository transfer as "pending" // it marks the repository transfer as "pending"
func CreatePendingRepositoryTransfer(doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error { func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repoID int64, teams []*organization.Team) error {
ctx, committer, err := db.TxContext(db.DefaultContext) return db.AutoTx(ctx, func(ctx context.Context) error {
if err != nil {
return err
}
defer committer.Close()
repo, err := repo_model.GetRepositoryByID(ctx, repoID) repo, err := repo_model.GetRepositoryByID(ctx, repoID)
if err != nil { if err != nil {
return err return err
@ -199,11 +194,8 @@ func CreatePendingRepositoryTransfer(doer, newOwner *user_model.User, repoID int
transfer.TeamIDs = append(transfer.TeamIDs, teams[k].ID) transfer.TeamIDs = append(transfer.TeamIDs, teams[k].ID)
} }
if err := db.Insert(ctx, transfer); err != nil { return db.Insert(ctx, transfer)
return err })
}
return committer.Commit()
} }
// TransferOwnership transfers all corresponding repository items from old user to new one. // TransferOwnership transfers all corresponding repository items from old user to new one.

View File

@ -6,6 +6,7 @@ package models
import ( import (
"testing" "testing"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -19,36 +20,36 @@ func TestRepositoryTransfer(t *testing.T) {
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
transfer, err := GetPendingRepositoryTransfer(repo) transfer, err := GetPendingRepositoryTransfer(db.DefaultContext, repo)
assert.NoError(t, err) assert.NoError(t, err)
assert.NotNil(t, transfer) assert.NotNil(t, transfer)
// Cancel transfer // Cancel transfer
assert.NoError(t, CancelRepositoryTransfer(repo)) assert.NoError(t, CancelRepositoryTransfer(repo))
transfer, err = GetPendingRepositoryTransfer(repo) transfer, err = GetPendingRepositoryTransfer(db.DefaultContext, repo)
assert.Error(t, err) assert.Error(t, err)
assert.Nil(t, transfer) assert.Nil(t, transfer)
assert.True(t, IsErrNoPendingTransfer(err)) assert.True(t, IsErrNoPendingTransfer(err))
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
assert.NoError(t, CreatePendingRepositoryTransfer(doer, user2, repo.ID, nil)) assert.NoError(t, CreatePendingRepositoryTransfer(db.DefaultContext, doer, user2, repo.ID, nil))
transfer, err = GetPendingRepositoryTransfer(repo) transfer, err = GetPendingRepositoryTransfer(db.DefaultContext, repo)
assert.Nil(t, err) assert.Nil(t, err)
assert.NoError(t, transfer.LoadAttributes()) assert.NoError(t, transfer.LoadAttributes(db.DefaultContext))
assert.Equal(t, "user2", transfer.Recipient.Name) assert.Equal(t, "user2", transfer.Recipient.Name)
user6 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) user6 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
// Only transfer can be started at any given time // Only transfer can be started at any given time
err = CreatePendingRepositoryTransfer(doer, user6, repo.ID, nil) err = CreatePendingRepositoryTransfer(db.DefaultContext, doer, user6, repo.ID, nil)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, IsErrRepoTransferInProgress(err)) assert.True(t, IsErrRepoTransferInProgress(err))
// Unknown user // Unknown user
err = CreatePendingRepositoryTransfer(doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil) err = CreatePendingRepositoryTransfer(db.DefaultContext, doer, &user_model.User{ID: 1000, LowerName: "user1000"}, repo.ID, nil)
assert.Error(t, err) assert.Error(t, err)
// Cancel transfer // Cancel transfer

View File

@ -110,7 +110,7 @@ func determineAccessMode(ctx *Context) (perm.AccessMode, error) {
return accessMode, err return accessMode, err
} }
for _, t := range teams { for _, t := range teams {
perm := t.UnitAccessModeCtx(ctx, unit.TypePackages) perm := t.UnitAccessMode(ctx, unit.TypePackages)
if accessMode < perm { if accessMode < perm {
accessMode = perm accessMode = perm
} }

View File

@ -163,13 +163,13 @@ func (r *Repository) CanUseTimetracker(issue *issues_model.Issue, user *user_mod
// 1. Is timetracker enabled // 1. Is timetracker enabled
// 2. Is the user a contributor, admin, poster or assignee and do the repository policies require this? // 2. Is the user a contributor, admin, poster or assignee and do the repository policies require this?
isAssigned, _ := issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, user) isAssigned, _ := issues_model.IsUserAssignedToIssue(db.DefaultContext, issue, user)
return r.Repository.IsTimetrackerEnabled() && (!r.Repository.AllowOnlyContributorsToTrackTime() || return r.Repository.IsTimetrackerEnabled(db.DefaultContext) && (!r.Repository.AllowOnlyContributorsToTrackTime(db.DefaultContext) ||
r.Permission.CanWriteIssuesOrPulls(issue.IsPull) || issue.IsPoster(user.ID) || isAssigned) r.Permission.CanWriteIssuesOrPulls(issue.IsPull) || issue.IsPoster(user.ID) || isAssigned)
} }
// CanCreateIssueDependencies returns whether or not a user can create dependencies. // CanCreateIssueDependencies returns whether or not a user can create dependencies.
func (r *Repository) CanCreateIssueDependencies(user *user_model.User, isPull bool) bool { func (r *Repository) CanCreateIssueDependencies(user *user_model.User, isPull bool) bool {
return r.Repository.IsDependenciesEnabled() && r.Permission.CanWriteIssuesOrPulls(isPull) return r.Repository.IsDependenciesEnabled(db.DefaultContext) && r.Permission.CanWriteIssuesOrPulls(isPull)
} }
// GetCommitsCount returns cached commit count for current view // GetCommitsCount returns cached commit count for current view
@ -528,12 +528,12 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.Data["RepoLink"] = ctx.Repo.RepoLink ctx.Data["RepoLink"] = ctx.Repo.RepoLink
ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
unit, err := ctx.Repo.Repository.GetUnit(unit_model.TypeExternalTracker) unit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeExternalTracker)
if err == nil { if err == nil {
ctx.Data["RepoExternalIssuesLink"] = unit.ExternalTrackerConfig().ExternalTrackerURL ctx.Data["RepoExternalIssuesLink"] = unit.ExternalTrackerConfig().ExternalTrackerURL
} }
ctx.Data["NumTags"], err = repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ ctx.Data["NumTags"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{
IncludeDrafts: true, IncludeDrafts: true,
IncludeTags: true, IncludeTags: true,
HasSha1: util.OptionalBoolTrue, // only draft releases which are created with existing tags HasSha1: util.OptionalBoolTrue, // only draft releases which are created with existing tags
@ -542,7 +542,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.ServerError("GetReleaseCountByRepoID", err) ctx.ServerError("GetReleaseCountByRepoID", err)
return return
} }
ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{}) ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{})
if err != nil { if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err) ctx.ServerError("GetReleaseCountByRepoID", err)
return return
@ -723,13 +723,13 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer { if ctx.Repo.Repository.Status == repo_model.RepositoryPendingTransfer {
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository) repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
if err != nil { if err != nil {
ctx.ServerError("GetPendingRepositoryTransfer", err) ctx.ServerError("GetPendingRepositoryTransfer", err)
return return
} }
if err := repoTransfer.LoadAttributes(); err != nil { if err := repoTransfer.LoadAttributes(ctx); err != nil {
ctx.ServerError("LoadRecipient", err) ctx.ServerError("LoadRecipient", err)
return return
} }

View File

@ -149,7 +149,7 @@ func ToTimelineComment(ctx context.Context, c *issues_model.Comment, doer *user_
var err error var err error
repo, err = repo_model.GetRepositoryByID(ctx, c.Label.RepoID) repo, err = repo_model.GetRepositoryByID(ctx, c.Label.RepoID)
if err != nil { if err != nil {
log.Error("GetRepositoryByIDCtx(%d): %v", c.Label.RepoID, err) log.Error("GetRepositoryByID(%d): %v", c.Label.RepoID, err)
return nil return nil
} }
} }

View File

@ -8,7 +8,6 @@ import (
"time" "time"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit" unit_model "code.gitea.io/gitea/models/unit"
@ -44,7 +43,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
hasIssues := false hasIssues := false
var externalTracker *api.ExternalTracker var externalTracker *api.ExternalTracker
var internalTracker *api.InternalTracker var internalTracker *api.InternalTracker
if unit, err := repo.GetUnit(unit_model.TypeIssues); err == nil { if unit, err := repo.GetUnit(ctx, unit_model.TypeIssues); err == nil {
config := unit.IssuesConfig() config := unit.IssuesConfig()
hasIssues = true hasIssues = true
internalTracker = &api.InternalTracker{ internalTracker = &api.InternalTracker{
@ -52,7 +51,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime, AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime,
EnableIssueDependencies: config.EnableDependencies, EnableIssueDependencies: config.EnableDependencies,
} }
} else if unit, err := repo.GetUnit(unit_model.TypeExternalTracker); err == nil { } else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalTracker); err == nil {
config := unit.ExternalTrackerConfig() config := unit.ExternalTrackerConfig()
hasIssues = true hasIssues = true
externalTracker = &api.ExternalTracker{ externalTracker = &api.ExternalTracker{
@ -64,9 +63,9 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
} }
hasWiki := false hasWiki := false
var externalWiki *api.ExternalWiki var externalWiki *api.ExternalWiki
if _, err := repo.GetUnit(unit_model.TypeWiki); err == nil { if _, err := repo.GetUnit(ctx, unit_model.TypeWiki); err == nil {
hasWiki = true hasWiki = true
} else if unit, err := repo.GetUnit(unit_model.TypeExternalWiki); err == nil { } else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalWiki); err == nil {
hasWiki = true hasWiki = true
config := unit.ExternalWikiConfig() config := unit.ExternalWikiConfig()
externalWiki = &api.ExternalWiki{ externalWiki = &api.ExternalWiki{
@ -82,7 +81,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
allowRebaseUpdate := false allowRebaseUpdate := false
defaultDeleteBranchAfterMerge := false defaultDeleteBranchAfterMerge := false
defaultMergeStyle := repo_model.MergeStyleMerge defaultMergeStyle := repo_model.MergeStyleMerge
if unit, err := repo.GetUnit(unit_model.TypePullRequests); err == nil { if unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests); err == nil {
config := unit.PullRequestsConfig() config := unit.PullRequestsConfig()
hasPullRequests = true hasPullRequests = true
ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts
@ -95,21 +94,21 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
defaultMergeStyle = config.GetDefaultMergeStyle() defaultMergeStyle = config.GetDefaultMergeStyle()
} }
hasProjects := false hasProjects := false
if _, err := repo.GetUnit(unit_model.TypeProjects); err == nil { if _, err := repo.GetUnit(ctx, unit_model.TypeProjects); err == nil {
hasProjects = true hasProjects = true
} }
if err := repo.GetOwner(db.DefaultContext); err != nil { if err := repo.GetOwner(ctx); err != nil {
return nil return nil
} }
numReleases, _ := repo_model.GetReleaseCountByRepoID(repo.ID, repo_model.FindReleasesOptions{IncludeDrafts: false, IncludeTags: false}) numReleases, _ := repo_model.GetReleaseCountByRepoID(ctx, repo.ID, repo_model.FindReleasesOptions{IncludeDrafts: false, IncludeTags: false})
mirrorInterval := "" mirrorInterval := ""
var mirrorUpdated time.Time var mirrorUpdated time.Time
if repo.IsMirror { if repo.IsMirror {
var err error var err error
repo.Mirror, err = repo_model.GetMirrorByRepoID(db.DefaultContext, repo.ID) repo.Mirror, err = repo_model.GetMirrorByRepoID(ctx, repo.ID)
if err == nil { if err == nil {
mirrorInterval = repo.Mirror.Interval.String() mirrorInterval = repo.Mirror.Interval.String()
mirrorUpdated = repo.Mirror.UpdatedUnix.AsTime() mirrorUpdated = repo.Mirror.UpdatedUnix.AsTime()
@ -118,11 +117,11 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, mode perm.Acc
var transfer *api.RepoTransfer var transfer *api.RepoTransfer
if repo.Status == repo_model.RepositoryPendingTransfer { if repo.Status == repo_model.RepositoryPendingTransfer {
t, err := models.GetPendingRepositoryTransfer(repo) t, err := models.GetPendingRepositoryTransfer(ctx, repo)
if err != nil && !models.IsErrNoPendingTransfer(err) { if err != nil && !models.IsErrNoPendingTransfer(err) {
log.Warn("GetPendingRepositoryTransfer: %v", err) log.Warn("GetPendingRepositoryTransfer: %v", err)
} else { } else {
if err := t.LoadAttributes(); err != nil { if err := t.LoadAttributes(ctx); err != nil {
log.Warn("LoadAttributes of RepoTransfer: %v", err) log.Warn("LoadAttributes of RepoTransfer: %v", err)
} else { } else {
transfer = ToRepoTransfer(t) transfer = ToRepoTransfer(t)

View File

@ -13,7 +13,8 @@ import (
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
) )
func addCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error { func AddCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
return db.AutoTx(ctx, func(ctx context.Context) error {
collaboration := &repo_model.Collaboration{ collaboration := &repo_model.Collaboration{
RepoID: repo.ID, RepoID: repo.ID,
UserID: u.ID, UserID: u.ID,
@ -32,11 +33,5 @@ func addCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_m
} }
return access_model.RecalculateUserAccess(ctx, repo, u.ID) return access_model.RecalculateUserAccess(ctx, repo, u.ID)
}
// AddCollaborator adds new collaboration to a repository with default access mode.
func AddCollaborator(repo *repo_model.Repository, u *user_model.User) error {
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
return addCollaborator(ctx, repo, u)
}) })
} }

View File

@ -25,7 +25,7 @@ func TestRepository_AddCollaborator(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
assert.NoError(t, repo.GetOwner(db.DefaultContext)) assert.NoError(t, repo.GetOwner(db.DefaultContext))
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}) user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
assert.NoError(t, AddCollaborator(repo, user)) assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID}) unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID})
} }
testSuccess(1, 4) testSuccess(1, 4)
@ -50,7 +50,7 @@ func TestRepoPermissionPublicNonOrgRepo(t *testing.T) {
} }
// change to collaborator // change to collaborator
assert.NoError(t, AddCollaborator(repo, user)) assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
assert.NoError(t, err) assert.NoError(t, err)
for _, unit := range repo.Units { for _, unit := range repo.Units {
@ -103,7 +103,7 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) {
} }
// change to collaborator to default write access // change to collaborator to default write access
assert.NoError(t, AddCollaborator(repo, user)) assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
assert.NoError(t, err) assert.NoError(t, err)
for _, unit := range repo.Units { for _, unit := range repo.Units {
@ -111,7 +111,7 @@ func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) {
assert.True(t, perm.CanWrite(unit.Type)) assert.True(t, perm.CanWrite(unit.Type))
} }
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
assert.NoError(t, err) assert.NoError(t, err)
for _, unit := range repo.Units { for _, unit := range repo.Units {
@ -155,7 +155,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) {
} }
// change to collaborator to default write access // change to collaborator to default write access
assert.NoError(t, AddCollaborator(repo, user)) assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
assert.NoError(t, err) assert.NoError(t, err)
for _, unit := range repo.Units { for _, unit := range repo.Units {
@ -163,7 +163,7 @@ func TestRepoPermissionPublicOrgRepo(t *testing.T) {
assert.True(t, perm.CanWrite(unit.Type)) assert.True(t, perm.CanWrite(unit.Type))
} }
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
assert.NoError(t, err) assert.NoError(t, err)
for _, unit := range repo.Units { for _, unit := range repo.Units {
@ -217,7 +217,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) {
} }
// change to collaborator to default write access // change to collaborator to default write access
assert.NoError(t, AddCollaborator(repo, user)) assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
assert.NoError(t, err) assert.NoError(t, err)
for _, unit := range repo.Units { for _, unit := range repo.Units {
@ -225,7 +225,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) {
assert.True(t, perm.CanWrite(unit.Type)) assert.True(t, perm.CanWrite(unit.Type))
} }
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
assert.NoError(t, err) assert.NoError(t, err)
for _, unit := range repo.Units { for _, unit := range repo.Units {

View File

@ -125,10 +125,10 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
return fmt.Errorf("IsUserRepoAdmin: %w", err) return fmt.Errorf("IsUserRepoAdmin: %w", err)
} else if !isAdmin { } else if !isAdmin {
// Make creator repo admin if it wasn't assigned automatically // Make creator repo admin if it wasn't assigned automatically
if err = addCollaborator(ctx, repo, doer); err != nil { if err = AddCollaborator(ctx, repo, doer); err != nil {
return fmt.Errorf("addCollaborator: %w", err) return fmt.Errorf("AddCollaborator: %w", err)
} }
if err = repo_model.ChangeCollaborationAccessModeCtx(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil { if err = repo_model.ChangeCollaborationAccessMode(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil {
return fmt.Errorf("ChangeCollaborationAccessModeCtx: %w", err) return fmt.Errorf("ChangeCollaborationAccessModeCtx: %w", err)
} }
} }

10
options/license/Symlinks Normal file
View File

@ -0,0 +1,10 @@
My "symlinks" utility pre-dates the "open source licensing"
fad by a number of years. Just to clarify, this is 100%
freeware, written entirely by myself. The intent is to use
it to detect missing/obsolete symlink targets on an installed
distro, before creating the "gold" (or "final") release discs.
Use and distribute and modify as you (or anyone
else) sees fit. There have no formal restrictions or
requirements whatsoever regarding distribution of either
binaries or source code, whether modified or original.

View File

@ -174,13 +174,13 @@ func AddCollaborator(ctx *context.APIContext) {
return return
} }
if err := repo_module.AddCollaborator(ctx.Repo.Repository, collaborator); err != nil { if err := repo_module.AddCollaborator(ctx, ctx.Repo.Repository, collaborator); err != nil {
ctx.Error(http.StatusInternalServerError, "AddCollaborator", err) ctx.Error(http.StatusInternalServerError, "AddCollaborator", err)
return return
} }
if form.Permission != nil { if form.Permission != nil {
if err := repo_model.ChangeCollaborationAccessMode(ctx.Repo.Repository, collaborator.ID, perm.ParseAccessMode(*form.Permission)); err != nil { if err := repo_model.ChangeCollaborationAccessMode(ctx, ctx.Repo.Repository, collaborator.ID, perm.ParseAccessMode(*form.Permission)); err != nil {
ctx.Error(http.StatusInternalServerError, "ChangeCollaborationAccessMode", err) ctx.Error(http.StatusInternalServerError, "ChangeCollaborationAccessMode", err)
return return
} }

View File

@ -18,7 +18,7 @@ import (
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/routers/api/v1/utils"
comment_service "code.gitea.io/gitea/services/comments" issue_service "code.gitea.io/gitea/services/issue"
) )
// ListIssueComments list all the comments of an issue // ListIssueComments list all the comments of an issue
@ -362,7 +362,7 @@ func CreateIssueComment(ctx *context.APIContext) {
return return
} }
comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil) comment, err := issue_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil)
if err != nil { if err != nil {
ctx.Error(http.StatusInternalServerError, "CreateIssueComment", err) ctx.Error(http.StatusInternalServerError, "CreateIssueComment", err)
return return
@ -556,7 +556,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
oldContent := comment.Content oldContent := comment.Content
comment.Content = form.Body comment.Content = form.Body
if err := comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil { if err := issue_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateComment", err) ctx.Error(http.StatusInternalServerError, "UpdateComment", err)
return return
} }
@ -655,7 +655,7 @@ func deleteIssueComment(ctx *context.APIContext) {
return return
} }
if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil { if err = issue_service.DeleteComment(ctx, ctx.Doer, comment); err != nil {
ctx.Error(http.StatusInternalServerError, "DeleteCommentByID", err) ctx.Error(http.StatusInternalServerError, "DeleteCommentByID", err)
return return
} }

View File

@ -15,7 +15,7 @@ import (
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/attachment" "code.gitea.io/gitea/services/attachment"
comment_service "code.gitea.io/gitea/services/comments" issue_service "code.gitea.io/gitea/services/issue"
) )
// GetIssueCommentAttachment gets a single attachment of the comment // GetIssueCommentAttachment gets a single attachment of the comment
@ -196,7 +196,7 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) {
return return
} }
if err = comment_service.UpdateComment(ctx, comment, ctx.Doer, comment.Content); err != nil { if err = issue_service.UpdateComment(ctx, comment, ctx.Doer, comment.Content); err != nil {
ctx.ServerError("UpdateComment", err) ctx.ServerError("UpdateComment", err)
return return
} }

View File

@ -71,7 +71,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
if !ctx.Repo.Repository.IsTimetrackerEnabled() { if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
ctx.NotFound("Timetracker is disabled") ctx.NotFound("Timetracker is disabled")
return return
} }
@ -190,7 +190,7 @@ func AddTime(ctx *context.APIContext) {
} }
if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) { if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
if !ctx.Repo.Repository.IsTimetrackerEnabled() { if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
ctx.Error(http.StatusBadRequest, "", "time tracking disabled") ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
return return
} }
@ -271,7 +271,7 @@ func ResetIssueTime(ctx *context.APIContext) {
} }
if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) { if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
if !ctx.Repo.Repository.IsTimetrackerEnabled() { if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"}) ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
return return
} }
@ -342,7 +342,7 @@ func DeleteTime(ctx *context.APIContext) {
} }
if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) { if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
if !ctx.Repo.Repository.IsTimetrackerEnabled() { if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"}) ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
return return
} }
@ -410,7 +410,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
// "403": // "403":
// "$ref": "#/responses/forbidden" // "$ref": "#/responses/forbidden"
if !ctx.Repo.Repository.IsTimetrackerEnabled() { if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
ctx.Error(http.StatusBadRequest, "", "time tracking disabled") ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
return return
} }
@ -498,7 +498,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
// "403": // "403":
// "$ref": "#/responses/forbidden" // "$ref": "#/responses/forbidden"
if !ctx.Repo.Repository.IsTimetrackerEnabled() { if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
ctx.Error(http.StatusBadRequest, "", "time tracking disabled") ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
return return
} }

View File

@ -731,7 +731,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
var units []repo_model.RepoUnit var units []repo_model.RepoUnit
var deleteUnitTypes []unit_model.Type var deleteUnitTypes []unit_model.Type
currHasIssues := repo.UnitEnabledCtx(ctx, unit_model.TypeIssues) currHasIssues := repo.UnitEnabled(ctx, unit_model.TypeIssues)
newHasIssues := currHasIssues newHasIssues := currHasIssues
if opts.HasIssues != nil { if opts.HasIssues != nil {
newHasIssues = *opts.HasIssues newHasIssues = *opts.HasIssues
@ -771,7 +771,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
AllowOnlyContributorsToTrackTime: opts.InternalTracker.AllowOnlyContributorsToTrackTime, AllowOnlyContributorsToTrackTime: opts.InternalTracker.AllowOnlyContributorsToTrackTime,
EnableDependencies: opts.InternalTracker.EnableIssueDependencies, EnableDependencies: opts.InternalTracker.EnableIssueDependencies,
} }
} else if unit, err := repo.GetUnit(unit_model.TypeIssues); err != nil { } else if unit, err := repo.GetUnit(ctx, unit_model.TypeIssues); err != nil {
// Unit type doesn't exist so we make a new config file with default values // Unit type doesn't exist so we make a new config file with default values
config = &repo_model.IssuesConfig{ config = &repo_model.IssuesConfig{
EnableTimetracker: true, EnableTimetracker: true,
@ -798,7 +798,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
} }
} }
currHasWiki := repo.UnitEnabledCtx(ctx, unit_model.TypeWiki) currHasWiki := repo.UnitEnabled(ctx, unit_model.TypeWiki)
newHasWiki := currHasWiki newHasWiki := currHasWiki
if opts.HasWiki != nil { if opts.HasWiki != nil {
newHasWiki = *opts.HasWiki newHasWiki = *opts.HasWiki
@ -838,7 +838,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
} }
} }
currHasPullRequests := repo.UnitEnabledCtx(ctx, unit_model.TypePullRequests) currHasPullRequests := repo.UnitEnabled(ctx, unit_model.TypePullRequests)
newHasPullRequests := currHasPullRequests newHasPullRequests := currHasPullRequests
if opts.HasPullRequests != nil { if opts.HasPullRequests != nil {
newHasPullRequests = *opts.HasPullRequests newHasPullRequests = *opts.HasPullRequests
@ -848,7 +848,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
// We do allow setting individual PR settings through the API, so // We do allow setting individual PR settings through the API, so
// we get the config settings and then set them // we get the config settings and then set them
// if those settings were provided in the opts. // if those settings were provided in the opts.
unit, err := repo.GetUnit(unit_model.TypePullRequests) unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests)
var config *repo_model.PullRequestsConfig var config *repo_model.PullRequestsConfig
if err != nil { if err != nil {
// Unit type doesn't exist so we make a new config file with default values // Unit type doesn't exist so we make a new config file with default values

View File

@ -105,7 +105,7 @@ func Transfer(ctx *context.APIContext) {
oldFullname := ctx.Repo.Repository.FullName() oldFullname := ctx.Repo.Repository.FullName()
if err := repo_service.StartRepositoryTransfer(ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil { if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
if models.IsErrRepoTransferInProgress(err) { if models.IsErrRepoTransferInProgress(err) {
ctx.Error(http.StatusConflict, "StartRepositoryTransfer", err) ctx.Error(http.StatusConflict, "StartRepositoryTransfer", err)
return return
@ -207,7 +207,7 @@ func RejectTransfer(ctx *context.APIContext) {
} }
func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error { func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository) repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
if err != nil { if err != nil {
if models.IsErrNoPendingTransfer(err) { if models.IsErrNoPendingTransfer(err) {
ctx.NotFound() ctx.NotFound()
@ -216,7 +216,7 @@ func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
return err return err
} }
if err := repoTransfer.LoadAttributes(); err != nil { if err := repoTransfer.LoadAttributes(ctx); err != nil {
return err return err
} }
@ -226,7 +226,7 @@ func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
} }
if accept { if accept {
return repo_service.TransferOwnership(repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams) return repo_service.TransferOwnership(ctx, repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams)
} }
return models.CancelRepositoryTransfer(ctx.Repo.Repository) return models.CancelRepositoryTransfer(ctx.Repo.Repository)

View File

@ -382,7 +382,7 @@ func ServCommand(ctx *context.PrivateContext) {
if results.IsWiki { if results.IsWiki {
// Ensure the wiki is enabled before we allow access to it // Ensure the wiki is enabled before we allow access to it
if _, err := repo.GetUnit(unit.TypeWiki); err != nil { if _, err := repo.GetUnit(ctx, unit.TypeWiki); err != nil {
if repo_model.IsErrUnitTypeNotExist(err) { if repo_model.IsErrUnitTypeNotExist(err) {
ctx.JSON(http.StatusForbidden, private.ErrServCommand{ ctx.JSON(http.StatusForbidden, private.ErrServCommand{
Results: results, Results: results,

View File

@ -68,6 +68,10 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions,
orderBy = "`user`.updated_unix ASC" orderBy = "`user`.updated_unix ASC"
case "reversealphabetically": case "reversealphabetically":
orderBy = "`user`.name DESC" orderBy = "`user`.name DESC"
case "lastlogin":
orderBy = "`user`.last_login_unix ASC"
case "reverselastlogin":
orderBy = "`user`.last_login_unix DESC"
case UserSearchDefaultSortType: // "alphabetically" case UserSearchDefaultSortType: // "alphabetically"
default: default:
orderBy = "`user`.name ASC" orderBy = "`user`.name ASC"

View File

@ -177,7 +177,7 @@ func CherryPickPost(ctx *context.Context) {
} }
} }
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) { if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName)) ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else { } else {
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName)) ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName))

View File

@ -577,7 +577,7 @@ func PrepareCompareDiff(
if (headCommitID == ci.CompareInfo.MergeBase && !ci.DirectComparison) || if (headCommitID == ci.CompareInfo.MergeBase && !ci.DirectComparison) ||
headCommitID == ci.CompareInfo.BaseCommitID { headCommitID == ci.CompareInfo.BaseCommitID {
ctx.Data["IsNothingToCompare"] = true ctx.Data["IsNothingToCompare"] = true
if unit, err := repo.GetUnit(unit.TypePullRequests); err == nil { if unit, err := repo.GetUnit(ctx, unit.TypePullRequests); err == nil {
config := unit.PullRequestsConfig() config := unit.PullRequestsConfig()
if !config.AutodetectManualMerge { if !config.AutodetectManualMerge {

View File

@ -328,7 +328,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
} }
} }
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) { if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName)) ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else { } else {
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath)) ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
@ -514,7 +514,7 @@ func DeleteFilePost(ctx *context.Context) {
} }
ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath)) ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) { if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName)) ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else { } else {
treePath := path.Dir(ctx.Repo.TreePath) treePath := path.Dir(ctx.Repo.TreePath)
@ -717,7 +717,7 @@ func UploadFilePost(ctx *context.Context) {
return return
} }
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) { if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName)) ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else { } else {
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath)) ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))

View File

@ -284,7 +284,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
if isWiki { if isWiki {
// Ensure the wiki is enabled before we allow access to it // Ensure the wiki is enabled before we allow access to it
if _, err := repo.GetUnit(unit.TypeWiki); err != nil { if _, err := repo.GetUnit(ctx, unit.TypeWiki); err != nil {
if repo_model.IsErrUnitTypeNotExist(err) { if repo_model.IsErrUnitTypeNotExist(err) {
ctx.PlainText(http.StatusForbidden, "repository wiki is disabled") ctx.PlainText(http.StatusForbidden, "repository wiki is disabled")
return return

View File

@ -47,7 +47,6 @@ import (
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/utils" "code.gitea.io/gitea/routers/utils"
asymkey_service "code.gitea.io/gitea/services/asymkey" asymkey_service "code.gitea.io/gitea/services/asymkey"
comment_service "code.gitea.io/gitea/services/comments"
"code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/forms"
issue_service "code.gitea.io/gitea/services/issue" issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull" pull_service "code.gitea.io/gitea/services/pull"
@ -114,7 +113,7 @@ func MustEnableIssues(ctx *context.Context) {
return return
} }
unit, err := ctx.Repo.Repository.GetUnit(unit.TypeExternalTracker) unit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalTracker)
if err == nil { if err == nil {
ctx.Redirect(unit.ExternalTrackerConfig().ExternalTrackerURL) ctx.Redirect(unit.ExternalTrackerConfig().ExternalTrackerURL)
return return
@ -1174,7 +1173,7 @@ func getBranchData(ctx *context.Context, issue *issues_model.Issue) {
func ViewIssue(ctx *context.Context) { func ViewIssue(ctx *context.Context) {
if ctx.Params(":type") == "issues" { if ctx.Params(":type") == "issues" {
// If issue was requested we check if repo has external tracker and redirect // If issue was requested we check if repo has external tracker and redirect
extIssueUnit, err := ctx.Repo.Repository.GetUnit(unit.TypeExternalTracker) extIssueUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalTracker)
if err == nil && extIssueUnit != nil { if err == nil && extIssueUnit != nil {
if extIssueUnit.ExternalTrackerConfig().ExternalTrackerStyle == markup.IssueNameStyleNumeric || extIssueUnit.ExternalTrackerConfig().ExternalTrackerStyle == "" { if extIssueUnit.ExternalTrackerConfig().ExternalTrackerStyle == markup.IssueNameStyleNumeric || extIssueUnit.ExternalTrackerConfig().ExternalTrackerStyle == "" {
metas := ctx.Repo.Repository.ComposeMetas() metas := ctx.Repo.Repository.ComposeMetas()
@ -1375,7 +1374,7 @@ func ViewIssue(ctx *context.Context) {
comment *issues_model.Comment comment *issues_model.Comment
participants = make([]*user_model.User, 1, 10) participants = make([]*user_model.User, 1, 10)
) )
if ctx.Repo.Repository.IsTimetrackerEnabled() { if ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
if ctx.IsSigned { if ctx.IsSigned {
// Deal with the stopwatch // Deal with the stopwatch
ctx.Data["IsStopwatchRunning"] = issues_model.StopwatchExists(ctx.Doer.ID, issue.ID) ctx.Data["IsStopwatchRunning"] = issues_model.StopwatchExists(ctx.Doer.ID, issue.ID)
@ -1636,7 +1635,7 @@ func ViewIssue(ctx *context.Context) {
} }
} }
prUnit, err := repo.GetUnit(unit.TypePullRequests) prUnit, err := repo.GetUnit(ctx, unit.TypePullRequests)
if err != nil { if err != nil {
ctx.ServerError("GetUnit", err) ctx.ServerError("GetUnit", err)
return return
@ -2709,7 +2708,7 @@ func NewComment(ctx *context.Context) {
return return
} }
comment, err := comment_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments) comment, err := issue_service.CreateIssueComment(ctx, ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments)
if err != nil { if err != nil {
ctx.ServerError("CreateIssueComment", err) ctx.ServerError("CreateIssueComment", err)
return return
@ -2749,8 +2748,7 @@ func UpdateCommentContent(ctx *context.Context) {
}) })
return return
} }
if err = issue_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
if err = comment_service.UpdateComment(ctx, comment, ctx.Doer, oldContent); err != nil {
ctx.ServerError("UpdateComment", err) ctx.ServerError("UpdateComment", err)
return return
} }
@ -2806,7 +2804,7 @@ func DeleteComment(ctx *context.Context) {
return return
} }
if err = comment_service.DeleteComment(ctx, ctx.Doer, comment); err != nil { if err = issue_service.DeleteComment(ctx, ctx.Doer, comment); err != nil {
ctx.ServerError("DeleteComment", err) ctx.ServerError("DeleteComment", err)
return return
} }

View File

@ -73,7 +73,7 @@ func Milestones(ctx *context.Context) {
ctx.ServerError("GetMilestones", err) ctx.ServerError("GetMilestones", err)
return return
} }
if ctx.Repo.Repository.IsTimetrackerEnabled() { if ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
if err := miles.LoadTotalTrackedTimes(); err != nil { if err := miles.LoadTotalTrackedTimes(); err != nil {
ctx.ServerError("LoadTotalTrackedTimes", err) ctx.ServerError("LoadTotalTrackedTimes", err)
return return

View File

@ -108,7 +108,7 @@ func NewDiffPatchPost(ctx *context.Context) {
} }
} }
if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(unit.TypePullRequests) { if form.CommitChoice == frmCommitChoiceNewBranch && ctx.Repo.Repository.UnitEnabled(ctx, unit.TypePullRequests) {
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName)) ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ctx.Repo.BranchName) + "..." + util.PathEscapeSegments(form.NewBranchName))
} else { } else {
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath)) ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))

View File

@ -196,7 +196,7 @@ func DeleteProject(ctx *context.Context) {
return return
} }
if err := project_model.DeleteProjectByID(p.ID); err != nil { if err := project_model.DeleteProjectByID(ctx, p.ID); err != nil {
ctx.Flash.Error("DeleteProjectByID: " + err.Error()) ctx.Flash.Error("DeleteProjectByID: " + err.Error())
} else { } else {
ctx.Flash.Success(ctx.Tr("repo.projects.deletion_success")) ctx.Flash.Success(ctx.Tr("repo.projects.deletion_success"))

View File

@ -135,7 +135,7 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
return return
} }
count, err := repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, opts) count, err := repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, opts)
if err != nil { if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err) ctx.ServerError("GetReleaseCountByRepoID", err)
return return

View File

@ -314,12 +314,12 @@ func Action(ctx *context.Context) {
} }
func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error { func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository) repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
if err != nil { if err != nil {
return err return err
} }
if err := repoTransfer.LoadAttributes(); err != nil { if err := repoTransfer.LoadAttributes(ctx); err != nil {
return err return err
} }
@ -333,7 +333,7 @@ func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
ctx.Repo.GitRepo = nil ctx.Repo.GitRepo = nil
} }
if err := repo_service.TransferOwnership(repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams); err != nil { if err := repo_service.TransferOwnership(ctx, repoTransfer.Doer, repoTransfer.Recipient, ctx.Repo.Repository, repoTransfer.Teams); err != nil {
return err return err
} }
ctx.Flash.Success(ctx.Tr("repo.settings.transfer.success")) ctx.Flash.Success(ctx.Tr("repo.settings.transfer.success"))

View File

@ -699,7 +699,7 @@ func SettingsPost(ctx *context.Context) {
ctx.Repo.GitRepo = nil ctx.Repo.GitRepo = nil
} }
if err := repo_service.StartRepositoryTransfer(ctx.Doer, newOwner, repo, nil); err != nil { if err := repo_service.StartRepositoryTransfer(ctx, ctx.Doer, newOwner, repo, nil); err != nil {
if repo_model.IsErrRepoAlreadyExist(err) { if repo_model.IsErrRepoAlreadyExist(err) {
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil) ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
} else if models.IsErrRepoTransferInProgress(err) { } else if models.IsErrRepoTransferInProgress(err) {
@ -721,7 +721,7 @@ func SettingsPost(ctx *context.Context) {
return return
} }
repoTransfer, err := models.GetPendingRepositoryTransfer(ctx.Repo.Repository) repoTransfer, err := models.GetPendingRepositoryTransfer(ctx, ctx.Repo.Repository)
if err != nil { if err != nil {
if models.IsErrNoPendingTransfer(err) { if models.IsErrNoPendingTransfer(err) {
ctx.Flash.Error("repo.settings.transfer_abort_invalid") ctx.Flash.Error("repo.settings.transfer_abort_invalid")
@ -733,7 +733,7 @@ func SettingsPost(ctx *context.Context) {
return return
} }
if err := repoTransfer.LoadAttributes(); err != nil { if err := repoTransfer.LoadAttributes(ctx); err != nil {
ctx.ServerError("LoadRecipient", err) ctx.ServerError("LoadRecipient", err)
return return
} }
@ -939,7 +939,7 @@ func CollaborationPost(ctx *context.Context) {
} }
} }
if err = repo_module.AddCollaborator(ctx.Repo.Repository, u); err != nil { if err = repo_module.AddCollaborator(ctx, ctx.Repo.Repository, u); err != nil {
ctx.ServerError("AddCollaborator", err) ctx.ServerError("AddCollaborator", err)
return return
} }
@ -955,6 +955,7 @@ func CollaborationPost(ctx *context.Context) {
// ChangeCollaborationAccessMode response for changing access of a collaboration // ChangeCollaborationAccessMode response for changing access of a collaboration
func ChangeCollaborationAccessMode(ctx *context.Context) { func ChangeCollaborationAccessMode(ctx *context.Context) {
if err := repo_model.ChangeCollaborationAccessMode( if err := repo_model.ChangeCollaborationAccessMode(
ctx,
ctx.Repo.Repository, ctx.Repo.Repository,
ctx.FormInt64("uid"), ctx.FormInt64("uid"),
perm.AccessMode(ctx.FormInt("mode"))); err != nil { perm.AccessMode(ctx.FormInt("mode"))); err != nil {

View File

@ -59,7 +59,7 @@ func MustEnableWiki(ctx *context.Context) {
return return
} }
unit, err := ctx.Repo.Repository.GetUnit(unit.TypeExternalWiki) unit, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalWiki)
if err == nil { if err == nil {
ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL) ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
return return

View File

@ -231,7 +231,7 @@ func Milestones(ctx *context.Context) {
return return
} }
if milestones[i].Repo.IsTimetrackerEnabled() { if milestones[i].Repo.IsTimetrackerEnabled(ctx) {
err := milestones[i].LoadTotalTrackedTime() err := milestones[i].LoadTotalTrackedTime()
if err != nil { if err != nil {
ctx.ServerError("LoadTotalTrackedTime", err) ctx.ServerError("LoadTotalTrackedTime", err)

View File

@ -206,7 +206,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to load pull issue. Error: %w", err) return nil, fmt.Errorf("Failed to load pull issue. Error: %w", err)
} }
comment, err := issues_model.CreatePushPullComment(ctx, pusher, pr, oldCommitID, opts.NewCommitIDs[i]) comment, err := pull_service.CreatePushPullComment(ctx, pusher, pr, oldCommitID, opts.NewCommitIDs[i])
if err == nil && comment != nil { if err == nil && comment != nil {
notification.NotifyPullRequestPushCommits(ctx, pusher, pr, comment) notification.NotifyPullRequestPushCommits(ctx, pusher, pr, comment)
} }

View File

@ -1,10 +1,11 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package comments package issue
import ( import (
"context" "context"
"fmt"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
@ -14,9 +15,58 @@ import (
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
) )
// CreateComment creates comment of issue or commit.
func CreateComment(opts *issues_model.CreateCommentOptions) (comment *issues_model.Comment, err error) {
ctx, committer, err := db.TxContext(db.DefaultContext)
if err != nil {
return nil, err
}
defer committer.Close()
comment, err = issues_model.CreateComment(ctx, opts)
if err != nil {
return nil, err
}
if err = committer.Commit(); err != nil {
return nil, err
}
return comment, nil
}
// CreateRefComment creates a commit reference comment to issue.
func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error {
if len(commitSHA) == 0 {
return fmt.Errorf("cannot create reference with empty commit SHA")
}
// Check if same reference from same commit has already existed.
has, err := db.GetEngine(db.DefaultContext).Get(&issues_model.Comment{
Type: issues_model.CommentTypeCommitRef,
IssueID: issue.ID,
CommitSHA: commitSHA,
})
if err != nil {
return fmt.Errorf("check reference comment: %w", err)
} else if has {
return nil
}
_, err = CreateComment(&issues_model.CreateCommentOptions{
Type: issues_model.CommentTypeCommitRef,
Doer: doer,
Repo: repo,
Issue: issue,
CommitSHA: commitSHA,
Content: content,
})
return err
}
// CreateIssueComment creates a plain issue comment. // CreateIssueComment creates a plain issue comment.
func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) { func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content string, attachments []string) (*issues_model.Comment, error) {
comment, err := issues_model.CreateComment(&issues_model.CreateCommentOptions{ comment, err := CreateComment(&issues_model.CreateCommentOptions{
Type: issues_model.CommentTypeComment, Type: issues_model.CommentTypeComment,
Doer: doer, Doer: doer,
Repo: repo, Repo: repo,

View File

@ -158,7 +158,7 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm
} }
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, html.EscapeString(repo.Link()), html.EscapeString(url.PathEscape(c.Sha1)), html.EscapeString(strings.SplitN(c.Message, "\n", 2)[0])) message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, html.EscapeString(repo.Link()), html.EscapeString(url.PathEscape(c.Sha1)), html.EscapeString(strings.SplitN(c.Message, "\n", 2)[0]))
if err = issues_model.CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil { if err = CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil {
return err return err
} }

View File

@ -54,7 +54,7 @@ func changeMilestoneAssign(ctx context.Context, doer *user_model.User, issue *is
OldMilestoneID: oldMilestoneID, OldMilestoneID: oldMilestoneID,
MilestoneID: issue.MilestoneID, MilestoneID: issue.MilestoneID,
} }
if _, err := issues_model.CreateCommentCtx(ctx, opts); err != nil { if _, err := issues_model.CreateComment(ctx, opts); err != nil {
return err return err
} }
} }

View File

@ -236,7 +236,7 @@ func manuallyMerged(ctx context.Context, pr *issues_model.PullRequest) bool {
return false return false
} }
if unit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests); err == nil { if unit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests); err == nil {
config := unit.PullRequestsConfig() config := unit.PullRequestsConfig()
if !config.AutodetectManualMerge { if !config.AutodetectManualMerge {
return false return false

162
services/pull/comment.go Normal file
View File

@ -0,0 +1,162 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package pull
import (
"context"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
issue_service "code.gitea.io/gitea/services/issue"
)
type commitBranchCheckItem struct {
Commit *git.Commit
Checked bool
}
func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
if startCommit.ID.String() == endCommitID {
return nil
}
checkStack := make([]string, 0, 10)
checkStack = append(checkStack, startCommit.ID.String())
for len(checkStack) > 0 {
commitID := checkStack[0]
checkStack = checkStack[1:]
item, ok := commitList[commitID]
if !ok {
continue
}
if item.Commit.ID.String() == endCommitID {
continue
}
if err := item.Commit.LoadBranchName(); err != nil {
return err
}
if item.Commit.Branch == baseBranch {
continue
}
if item.Checked {
continue
}
item.Checked = true
parentNum := item.Commit.ParentCount()
for i := 0; i < parentNum; i++ {
parentCommit, err := item.Commit.Parent(i)
if err != nil {
return err
}
checkStack = append(checkStack, parentCommit.ID.String())
}
}
return nil
}
// getCommitIDsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
// isForcePush will be true if oldCommit isn't on the branch
// Commit on baseBranch will skip
func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) {
repoPath := repo.RepoPath()
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath)
if err != nil {
return nil, false, err
}
defer closer.Close()
oldCommit, err := gitRepo.GetCommit(oldCommitID)
if err != nil {
return nil, false, err
}
if err = oldCommit.LoadBranchName(); err != nil {
return nil, false, err
}
if len(oldCommit.Branch) == 0 {
commitIDs = make([]string, 2)
commitIDs[0] = oldCommitID
commitIDs[1] = newCommitID
return commitIDs, true, err
}
newCommit, err := gitRepo.GetCommit(newCommitID)
if err != nil {
return nil, false, err
}
commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
if err != nil {
return nil, false, err
}
commitIDs = make([]string, 0, len(commits))
commitChecks := make(map[string]*commitBranchCheckItem)
for _, commit := range commits {
commitChecks[commit.ID.String()] = &commitBranchCheckItem{
Commit: commit,
Checked: false,
}
}
if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
return
}
for i := len(commits) - 1; i >= 0; i-- {
commitID := commits[i].ID.String()
if item, ok := commitChecks[commitID]; ok && item.Checked {
commitIDs = append(commitIDs, commitID)
}
}
return commitIDs, isForcePush, err
}
// CreatePushPullComment create push code to pull base comment
func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *issues_model.PullRequest, oldCommitID, newCommitID string) (comment *issues_model.Comment, err error) {
if pr.HasMerged || oldCommitID == "" || newCommitID == "" {
return nil, nil
}
ops := &issues_model.CreateCommentOptions{
Type: issues_model.CommentTypePullRequestPush,
Doer: pusher,
Repo: pr.BaseRepo,
}
var data issues_model.PushActionContent
data.CommitIDs, data.IsForcePush, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch)
if err != nil {
return nil, err
}
ops.Issue = pr.Issue
dataJSON, err := json.Marshal(data)
if err != nil {
return nil, err
}
ops.Content = string(dataJSON)
comment, err = issue_service.CreateComment(ops)
return comment, err
}

View File

@ -54,7 +54,7 @@ func GetDefaultMergeMessage(ctx context.Context, baseGitRepo *git.Repository, pr
return "", err return "", err
} }
isExternalTracker := pr.BaseRepo.UnitEnabled(unit.TypeExternalTracker) isExternalTracker := pr.BaseRepo.UnitEnabled(ctx, unit.TypeExternalTracker)
issueReference := "#" issueReference := "#"
if isExternalTracker { if isExternalTracker {
issueReference = "!" issueReference = "!"
@ -145,11 +145,11 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID)) defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))
// Removing an auto merge pull and ignore if not exist // Removing an auto merge pull and ignore if not exist
if err := pull_model.DeleteScheduledAutoMerge(db.DefaultContext, pr.ID); err != nil && !db.IsErrNotExist(err) { if err := pull_model.DeleteScheduledAutoMerge(ctx, pr.ID); err != nil && !db.IsErrNotExist(err) {
return err return err
} }
prUnit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests) prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
if err != nil { if err != nil {
log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err) log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err)
return err return err
@ -828,7 +828,7 @@ func MergedManually(pr *issues_model.PullRequest, doer *user_model.User, baseGit
defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID)) defer pullWorkingPool.CheckOut(fmt.Sprint(pr.ID))
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error { if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
prUnit, err := pr.BaseRepo.GetUnitCtx(ctx, unit.TypePullRequests) prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
if err != nil { if err != nil {
return err return err
} }

View File

@ -354,7 +354,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
} }
// 5. Now get the pull request configuration to check if we need to ignore whitespace // 5. Now get the pull request configuration to check if we need to ignore whitespace
prUnit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests) prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -123,7 +123,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, pull *issu
Content: string(dataJSON), Content: string(dataJSON),
} }
_, _ = issues_model.CreateComment(ops) _, _ = issue_service.CreateComment(ops)
} }
return nil return nil
@ -222,7 +222,7 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer
OldRef: oldBranch, OldRef: oldBranch,
NewRef: targetBranch, NewRef: targetBranch,
} }
if _, err = issues_model.CreateComment(options); err != nil { if _, err = issue_service.CreateComment(options); err != nil {
return fmt.Errorf("CreateChangeTargetBranchComment: %w", err) return fmt.Errorf("CreateChangeTargetBranchComment: %w", err)
} }
@ -317,7 +317,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
} }
AddToTaskQueue(pr) AddToTaskQueue(pr)
comment, err := issues_model.CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID) comment, err := CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID)
if err == nil && comment != nil { if err == nil && comment != nil {
notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment) notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment)
} }

View File

@ -20,6 +20,7 @@ import (
"code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
issue_service "code.gitea.io/gitea/services/issue"
) )
// CreateCodeComment creates a comment on the code line // CreateCodeComment creates a comment on the code line
@ -202,7 +203,7 @@ func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_mo
return nil, err return nil, err
} }
} }
return issues_model.CreateComment(&issues_model.CreateCommentOptions{ return issue_service.CreateComment(&issues_model.CreateCommentOptions{
Type: issues_model.CommentTypeCode, Type: issues_model.CommentTypeCode,
Doer: doer, Doer: doer,
Repo: repo, Repo: repo,
@ -322,7 +323,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
return return
} }
comment, err = issues_model.CreateComment(&issues_model.CreateCommentOptions{ comment, err = issue_service.CreateComment(&issues_model.CreateCommentOptions{
Doer: doer, Doer: doer,
Content: message, Content: message,
Type: issues_model.CommentTypeDismissReview, Type: issues_model.CommentTypeDismissReview,

View File

@ -106,7 +106,7 @@ func IsUserAllowedToUpdate(ctx context.Context, pull *issues_model.PullRequest,
// can't do rebase on protected branch because need force push // can't do rebase on protected branch because need force push
if pr.ProtectedBranch == nil { if pr.ProtectedBranch == nil {
prUnit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests) prUnit, err := pr.BaseRepo.GetUnit(ctx, unit.TypePullRequests)
if err != nil { if err != nil {
log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err) log.Error("pr.BaseRepo.GetUnit(unit.TypePullRequests): %v", err)
return false, false, err return false, false, err

View File

@ -64,7 +64,7 @@ func DeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_mod
func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) { func PushCreateRepo(authUser, owner *user_model.User, repoName string) (*repo_model.Repository, error) {
if !authUser.IsAdmin { if !authUser.IsAdmin {
if owner.IsOrganization() { if owner.IsOrganization() {
if ok, err := organization.CanCreateOrgRepo(owner.ID, authUser.ID); err != nil { if ok, err := organization.CanCreateOrgRepo(db.DefaultContext, owner.ID, authUser.ID); err != nil {
return nil, err return nil, err
} else if !ok { } else if !ok {
return nil, fmt.Errorf("cannot push-create repository for org") return nil, fmt.Errorf("cannot push-create repository for org")

View File

@ -4,6 +4,7 @@
package repository package repository
import ( import (
"context"
"fmt" "fmt"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
@ -24,8 +25,8 @@ import (
var repoWorkingPool = sync.NewExclusivePool() var repoWorkingPool = sync.NewExclusivePool()
// TransferOwnership transfers all corresponding setting from old user to new one. // TransferOwnership transfers all corresponding setting from old user to new one.
func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error { func TransferOwnership(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
if err := repo.GetOwner(db.DefaultContext); err != nil { if err := repo.GetOwner(ctx); err != nil {
return err return err
} }
for _, team := range teams { for _, team := range teams {
@ -43,18 +44,18 @@ func TransferOwnership(doer, newOwner *user_model.User, repo *repo_model.Reposit
} }
repoWorkingPool.CheckOut(fmt.Sprint(repo.ID)) repoWorkingPool.CheckOut(fmt.Sprint(repo.ID))
newRepo, err := repo_model.GetRepositoryByID(db.DefaultContext, repo.ID) newRepo, err := repo_model.GetRepositoryByID(ctx, repo.ID)
if err != nil { if err != nil {
return err return err
} }
for _, team := range teams { for _, team := range teams {
if err := models.AddRepository(db.DefaultContext, team, newRepo); err != nil { if err := models.AddRepository(ctx, team, newRepo); err != nil {
return err return err
} }
} }
notification.NotifyTransferRepository(db.DefaultContext, doer, repo, oldOwner.Name) notification.NotifyTransferRepository(ctx, doer, repo, oldOwner.Name)
return nil return nil
} }
@ -84,49 +85,49 @@ func ChangeRepositoryName(doer *user_model.User, repo *repo_model.Repository, ne
// StartRepositoryTransfer transfer a repo from one owner to a new one. // StartRepositoryTransfer transfer a repo from one owner to a new one.
// it make repository into pending transfer state, if doer can not create repo for new owner. // it make repository into pending transfer state, if doer can not create repo for new owner.
func StartRepositoryTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error { func StartRepositoryTransfer(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository, teams []*organization.Team) error {
if err := models.TestRepositoryReadyForTransfer(repo.Status); err != nil { if err := models.TestRepositoryReadyForTransfer(repo.Status); err != nil {
return err return err
} }
// Admin is always allowed to transfer || user transfer repo back to his account // Admin is always allowed to transfer || user transfer repo back to his account
if doer.IsAdmin || doer.ID == newOwner.ID { if doer.IsAdmin || doer.ID == newOwner.ID {
return TransferOwnership(doer, newOwner, repo, teams) return TransferOwnership(ctx, doer, newOwner, repo, teams)
} }
// If new owner is an org and user can create repos he can transfer directly too // If new owner is an org and user can create repos he can transfer directly too
if newOwner.IsOrganization() { if newOwner.IsOrganization() {
allowed, err := organization.CanCreateOrgRepo(newOwner.ID, doer.ID) allowed, err := organization.CanCreateOrgRepo(ctx, newOwner.ID, doer.ID)
if err != nil { if err != nil {
return err return err
} }
if allowed { if allowed {
return TransferOwnership(doer, newOwner, repo, teams) return TransferOwnership(ctx, doer, newOwner, repo, teams)
} }
} }
// In case the new owner would not have sufficient access to the repo, give access rights for read // In case the new owner would not have sufficient access to the repo, give access rights for read
hasAccess, err := access_model.HasAccess(db.DefaultContext, newOwner.ID, repo) hasAccess, err := access_model.HasAccess(ctx, newOwner.ID, repo)
if err != nil { if err != nil {
return err return err
} }
if !hasAccess { if !hasAccess {
if err := repo_module.AddCollaborator(repo, newOwner); err != nil { if err := repo_module.AddCollaborator(ctx, repo, newOwner); err != nil {
return err return err
} }
if err := repo_model.ChangeCollaborationAccessMode(repo, newOwner.ID, perm.AccessModeRead); err != nil { if err := repo_model.ChangeCollaborationAccessMode(ctx, repo, newOwner.ID, perm.AccessModeRead); err != nil {
return err return err
} }
} }
// Make repo as pending for transfer // Make repo as pending for transfer
repo.Status = repo_model.RepositoryPendingTransfer repo.Status = repo_model.RepositoryPendingTransfer
if err := models.CreatePendingRepositoryTransfer(doer, newOwner, repo.ID, teams); err != nil { if err := models.CreatePendingRepositoryTransfer(ctx, doer, newOwner, repo.ID, teams); err != nil {
return err return err
} }
// notify users who are able to accept / reject transfer // notify users who are able to accept / reject transfer
notification.NotifyRepoPendingTransfer(db.DefaultContext, doer, newOwner, repo) notification.NotifyRepoPendingTransfer(ctx, doer, newOwner, repo)
return nil return nil
} }

View File

@ -37,7 +37,7 @@ func TestTransferOwnership(t *testing.T) {
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
repo.Owner = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) repo.Owner = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
assert.NoError(t, TransferOwnership(doer, doer, repo, nil)) assert.NoError(t, TransferOwnership(db.DefaultContext, doer, doer, repo, nil))
transferredRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) transferredRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
assert.EqualValues(t, 2, transferredRepo.OwnerID) assert.EqualValues(t, 2, transferredRepo.OwnerID)
@ -70,7 +70,7 @@ func TestStartRepositoryTransferSetPermission(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.False(t, hasAccess) assert.False(t, hasAccess)
assert.NoError(t, StartRepositoryTransfer(doer, recipient, repo, nil)) assert.NoError(t, StartRepositoryTransfer(db.DefaultContext, doer, recipient, repo, nil))
hasAccess, err = access_model.HasAccess(db.DefaultContext, recipient.ID, repo) hasAccess, err = access_model.HasAccess(db.DefaultContext, recipient.ID, repo)
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -39,7 +39,6 @@ apps:
command: usr/bin/sqlite3 command: usr/bin/sqlite3
parts: parts:
gitea: gitea:
plugin: make plugin: make
source: . source: .

View File

@ -6,12 +6,12 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "oldest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a> <a class="{{if or (eq .SortType "oldest") (not .SortType)}}active {{end}}item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a> <a class="{{if eq .SortType "newest"}}active {{end}}item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> <a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a> <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a> <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -15,10 +15,10 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "email") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=email&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.email"}}</a> <a class="{{if or (eq .SortType "email") (not .SortType)}}active {{end}}item" href="{{$.Link}}?sort=email&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.email"}}</a>
<a class="{{if eq .SortType "reverseemail"}}active{{end}} item" href="{{$.Link}}?sort=reverseemail&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.email_reverse"}}</a> <a class="{{if eq .SortType "reverseemail"}}active {{end}}item" href="{{$.Link}}?sort=reverseemail&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.email_reverse"}}</a>
<a class="{{if eq .SortType "username"}}active{{end}} item" href="{{$.Link}}?sort=username&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.name"}}</a> <a class="{{if eq .SortType "username"}}active {{end}}item" href="{{$.Link}}?sort=username&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.name"}}</a>
<a class="{{if eq .SortType "reverseusername"}}active{{end}} item" href="{{$.Link}}?sort=reverseusername&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.name_reverse"}}</a> <a class="{{if eq .SortType "reverseusername"}}active {{end}}item" href="{{$.Link}}?sort=reverseusername&q={{$.Keyword}}">{{.locale.Tr "admin.emails.filter_sort.name_reverse"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,50 +1,49 @@
<div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar"> <div class="ui secondary pointing tabular top attached borderless menu stackable new-menu navbar">
<div class="new-menu-inner"> <div class="new-menu-inner">
<a class="{{if .PageIsAdminDashboard}}active{{end}} item" href="{{AppSubUrl}}/admin"> <a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/admin">
{{.locale.Tr "admin.dashboard"}} {{.locale.Tr "admin.dashboard"}}
</a> </a>
<a class="{{if .PageIsAdminUsers}}active{{end}} item" href="{{AppSubUrl}}/admin/users"> <a class="{{if .PageIsAdminUsers}}active {{end}}item" href="{{AppSubUrl}}/admin/users">
{{.locale.Tr "admin.users"}} {{.locale.Tr "admin.users"}}
</a> </a>
<a class="{{if .PageIsAdminOrganizations}}active{{end}} item" href="{{AppSubUrl}}/admin/orgs"> <a class="{{if .PageIsAdminOrganizations}}active {{end}}item" href="{{AppSubUrl}}/admin/orgs">
{{.locale.Tr "admin.organizations"}} {{.locale.Tr "admin.organizations"}}
</a> </a>
<a class="{{if .PageIsAdminRepositories}}active{{end}} item" href="{{AppSubUrl}}/admin/repos"> <a class="{{if .PageIsAdminRepositories}}active {{end}}item" href="{{AppSubUrl}}/admin/repos">
{{.locale.Tr "admin.repositories"}} {{.locale.Tr "admin.repositories"}}
</a> </a>
{{if .EnablePackages}} {{if .EnablePackages}}
<a class="{{if .PageIsAdminPackages}}active{{end}} item" href="{{AppSubUrl}}/admin/packages"> <a class="{{if .PageIsAdminPackages}}active {{end}}item" href="{{AppSubUrl}}/admin/packages">
{{.locale.Tr "packages.title"}} {{.locale.Tr "packages.title"}}
</a> </a>
{{end}} {{end}}
{{if not DisableWebhooks}} {{if not DisableWebhooks}}
<a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks"> <a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active {{end}}item" href="{{AppSubUrl}}/admin/hooks">
{{.locale.Tr "admin.hooks"}} {{.locale.Tr "admin.hooks"}}
</a> </a>
{{end}} {{end}}
<a class="{{if .PageIsAdminAuthentications}}active{{end}} item" href="{{AppSubUrl}}/admin/auths"> <a class="{{if .PageIsAdminAuthentications}}active {{end}}item" href="{{AppSubUrl}}/admin/auths">
{{.locale.Tr "admin.authentication"}} {{.locale.Tr "admin.authentication"}}
</a> </a>
<a class="{{if .PageIsAdminEmails}}active{{end}} item" href="{{AppSubUrl}}/admin/emails"> <a class="{{if .PageIsAdminEmails}}active {{end}}item" href="{{AppSubUrl}}/admin/emails">
{{.locale.Tr "admin.emails"}} {{.locale.Tr "admin.emails"}}
</a> </a>
{{if .EnableOAuth2}} {{if .EnableOAuth2}}
<a class="{{if .PageIsAdminApplications}}active{{end}} item" href="{{AppSubUrl}}/admin/applications"> <a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/admin/applications">
{{.locale.Tr "settings.applications"}} {{.locale.Tr "settings.applications"}}
</a> </a>
{{end}} {{end}}
{{if .EnableActions}} <a class="{{if .PageIsAdminRunners}}active {{end}} item" href="{{AppSubUrl}}/admin/runners">
<a class="{{if .PageIsAdminRunners}}active{{end}} item" href="{{AppSubUrl}}/admin/runners">
{{.locale.Tr "admin.runners"}} {{.locale.Tr "admin.runners"}}
</a> </a>
{{end}} {{end}}
<a class="{{if .PageIsAdminConfig}}active{{end}} item" href="{{AppSubUrl}}/admin/config"> <a class="{{if .PageIsAdminConfig}}active {{end}} item" href="{{AppSubUrl}}/admin/config">
{{.locale.Tr "admin.config"}} {{.locale.Tr "admin.config"}}
</a> </a>
<a class="{{if .PageIsAdminNotices}}active{{end}} item" href="{{AppSubUrl}}/admin/notices"> <a class="{{if .PageIsAdminNotices}}active {{end}}item" href="{{AppSubUrl}}/admin/notices">
{{.locale.Tr "admin.notices"}} {{.locale.Tr "admin.notices"}}
</a> </a>
<a class="{{if .PageIsAdminMonitor}}active{{end}} item" href="{{AppSubUrl}}/admin/monitor"> <a class="{{if .PageIsAdminMonitor}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor">
{{.locale.Tr "admin.monitor"}} {{.locale.Tr "admin.monitor"}}
</a> </a>
</div> </div>

View File

@ -6,18 +6,18 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "oldest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a> <a class="{{if or (eq .SortType "oldest") (not .SortType)}}active {{end}}item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a> <a class="{{if eq .SortType "newest"}}active {{end}}item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> <a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a> <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a> <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.moststars"}}</a> <a class="{{if eq .SortType "moststars"}}active {{end}}item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.moststars"}}</a>
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.feweststars"}}</a> <a class="{{if eq .SortType "feweststars"}}active {{end}}item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.feweststars"}}</a>
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.mostforks"}}</a> <a class="{{if eq .SortType "mostforks"}}active {{end}}item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.mostforks"}}</a>
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.fewestforks"}}</a> <a class="{{if eq .SortType "fewestforks"}}active {{end}}item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.fewestforks"}}</a>
<a class="{{if eq .SortType "size"}}active{{end}} item" href="{{$.Link}}?sort=size&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.by_size"}}</a> <a class="{{if eq .SortType "size"}}active {{end}}item" href="{{$.Link}}?sort=size&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.by_size"}}</a>
<a class="{{if eq .SortType "reversesize"}}active{{end}} item" href="{{$.Link}}?sort=reversesize&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_by_size"}}</a> <a class="{{if eq .SortType "reversesize"}}active {{end}}item" href="{{$.Link}}?sort=reversesize&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_by_size"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -76,9 +76,9 @@
<th>{{.locale.Tr "admin.users.2fa"}}</th> <th>{{.locale.Tr "admin.users.2fa"}}</th>
<th>{{.locale.Tr "admin.users.repos"}}</th> <th>{{.locale.Tr "admin.users.repos"}}</th>
<th>{{.locale.Tr "admin.users.created"}}</th> <th>{{.locale.Tr "admin.users.created"}}</th>
<th data-sortt-asc="leastupdate" data-sortt-desc="recentupdate"> <th data-sortt-asc="lastlogin" data-sortt-desc="reverselastlogin">
{{.locale.Tr "admin.users.last_login"}} {{.locale.Tr "admin.users.last_login"}}
{{SortArrow "leastupdate" "recentupdate" $.SortType false}} {{SortArrow "lastlogin" "reverselastlogin" $.SortType false}}
</th> </th>
<th>{{.locale.Tr "admin.users.edit"}}</th> <th>{{.locale.Tr "admin.users.edit"}}</th>
</tr> </tr>

View File

@ -175,7 +175,7 @@
{{svg "octicon-bell"}} {{svg "octicon-bell"}}
{{.locale.Tr "notification.subscriptions"}}<!-- Subscriptions --> {{.locale.Tr "notification.subscriptions"}}<!-- Subscriptions -->
</a> </a>
<a class="{{if .PageIsUserSettings}}active{{end}} item" href="{{AppSubUrl}}/user/settings"> <a class="{{if .PageIsUserSettings}}active {{end}}item" href="{{AppSubUrl}}/user/settings">
{{svg "octicon-tools"}} {{svg "octicon-tools"}}
{{.locale.Tr "your_settings"}}<!-- Your settings --> {{.locale.Tr "your_settings"}}<!-- Your settings -->
</a> </a>
@ -186,7 +186,7 @@
{{if .IsAdmin}} {{if .IsAdmin}}
<div class="divider"></div> <div class="divider"></div>
<a class="{{if .PageIsAdmin}}active{{end}} item" href="{{AppSubUrl}}/admin"> <a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/admin">
{{svg "octicon-server"}} {{svg "octicon-server"}}
{{.locale.Tr "admin_panel"}}<!-- Admin Panel --> {{.locale.Tr "admin_panel"}}<!-- Admin Panel -->
</a> </a>

View File

@ -15,7 +15,7 @@
{{if eq .Num -1}} {{if eq .Num -1}}
<a class="disabled item">...</a> <a class="disabled item">...</a>
{{else}} {{else}}
<a class="{{if .IsCurrent}}active{{end}} item content-center" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}>{{.Num}}</a> <a class="{{if .IsCurrent}}active {{end}}item content-center" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}>{{.Num}}</a>
{{end}} {{end}}
{{end}} {{end}}
<a class="{{if not .HasNext}}disabled{{end}} item navigation" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}> <a class="{{if not .HasNext}}disabled{{end}} item navigation" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}>

View File

@ -1,17 +1,17 @@
<div class="ui secondary pointing tabular top attached borderless stackable menu new-menu navbar"> <div class="ui secondary pointing tabular top attached borderless stackable menu new-menu navbar">
<a class="{{if .PageIsExploreRepositories}}active{{end}} item" href="{{AppSubUrl}}/explore/repos"> <a class="{{if .PageIsExploreRepositories}}active {{end}}item" href="{{AppSubUrl}}/explore/repos">
{{svg "octicon-repo"}} {{.locale.Tr "explore.repos"}} {{svg "octicon-repo"}} {{.locale.Tr "explore.repos"}}
</a> </a>
{{if not .UsersIsDisabled}} {{if not .UsersIsDisabled}}
<a class="{{if .PageIsExploreUsers}}active{{end}} item" href="{{AppSubUrl}}/explore/users"> <a class="{{if .PageIsExploreUsers}}active {{end}}item" href="{{AppSubUrl}}/explore/users">
{{svg "octicon-person"}} {{.locale.Tr "explore.users"}} {{svg "octicon-person"}} {{.locale.Tr "explore.users"}}
</a> </a>
{{end}} {{end}}
<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"}} {{.locale.Tr "explore.organizations"}} {{svg "octicon-organization"}} {{.locale.Tr "explore.organizations"}}
</a> </a>
{{if .IsRepoIndexerEnabled}} {{if .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"}} {{.locale.Tr "explore.code"}} {{svg "octicon-code"}} {{.locale.Tr "explore.code"}}
</a> </a>
{{end}} {{end}}

View File

@ -6,18 +6,18 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a> <a class="{{if eq .SortType "newest"}}active {{end}}item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a> <a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> <a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a> <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a> <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
{{if not .DisableStars}} {{if not .DisableStars}}
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.moststars"}}</a> <a class="{{if eq .SortType "moststars"}}active {{end}}item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.moststars"}}</a>
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.feweststars"}}</a> <a class="{{if eq .SortType "feweststars"}}active {{end}}item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.feweststars"}}</a>
{{end}} {{end}}
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.mostforks"}}</a> <a class="{{if eq .SortType "mostforks"}}active {{end}}item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.mostforks"}}</a>
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.fewestforks"}}</a> <a class="{{if eq .SortType "fewestforks"}}active {{end}}item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&language={{$.Language}}">{{.locale.Tr "repo.issues.filter_sort.fewestforks"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,12 +6,12 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a> <a class="{{if eq .SortType "newest"}}active {{end}}item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a> <a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> <a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a> <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a> <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,36 +1,36 @@
<div class="four wide column"> <div class="four wide column">
<div class="ui fluid vertical menu"> <div class="ui fluid vertical menu">
<div class="header item">{{.locale.Tr "org.settings"}}</div> <div class="header item">{{.locale.Tr "org.settings"}}</div>
<a class="{{if .PageIsSettingsOptions}}active{{end}} item" href="{{.OrgLink}}/settings"> <a class="{{if .PageIsSettingsOptions}}active {{end}}item" href="{{.OrgLink}}/settings">
{{.locale.Tr "org.settings.options"}} {{.locale.Tr "org.settings.options"}}
</a> </a>
{{if not DisableWebhooks}} {{if not DisableWebhooks}}
<a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.OrgLink}}/settings/hooks"> <a class="{{if .PageIsSettingsHooks}}active {{end}}item" href="{{.OrgLink}}/settings/hooks">
{{.locale.Tr "repo.settings.hooks"}} {{.locale.Tr "repo.settings.hooks"}}
</a> </a>
{{end}} {{end}}
<a class="{{if .PageIsOrgSettingsLabels}}active{{end}} item" href="{{.OrgLink}}/settings/labels"> <a class="{{if .PageIsOrgSettingsLabels}}active {{end}}item" href="{{.OrgLink}}/settings/labels">
{{.locale.Tr "repo.labels"}} {{.locale.Tr "repo.labels"}}
</a> </a>
{{if .EnableOAuth2}} {{if .EnableOAuth2}}
<a class="{{if .PageIsSettingsApplications}}active{{end}} item" href="{{.OrgLink}}/settings/applications"> <a class="{{if .PageIsSettingsApplications}}active {{end}}item" href="{{.OrgLink}}/settings/applications">
{{.locale.Tr "settings.applications"}} {{.locale.Tr "settings.applications"}}
</a> </a>
{{end}} {{end}}
{{if .EnablePackages}} {{if .EnablePackages}}
<a class="{{if .PageIsSettingsPackages}}active{{end}} item" href="{{.OrgLink}}/settings/packages"> <a class="{{if .PageIsSettingsPackages}}active {{end}}item" href="{{.OrgLink}}/settings/packages">
{{.locale.Tr "packages.title"}} {{.locale.Tr "packages.title"}}
</a> </a>
{{end}} {{end}}
{{if .EnableActions}} {{if .EnableActions}}
<a class="{{if .PageIsOrgSettingsRunners}}active{{end}} item" href="{{.OrgLink}}/settings/runners"> <a class="{{if .PageIsOrgSettingsRunners}}active {{end}} item" href="{{.OrgLink}}/settings/runners">
{{.locale.Tr "repo.runners"}} {{.locale.Tr "repo.runners"}}
</a> </a>
{{end}} {{end}}
<a class="{{if .PageIsOrgSettingsSecrets}}active{{end}} item" href="{{.OrgLink}}/settings/secrets"> <a class="{{if .PageIsOrgSettingsSecrets}}active {{end}} item" href="{{.OrgLink}}/settings/secrets">
{{.locale.Tr "org.settings.secrets"}} {{.locale.Tr "org.settings.secrets"}}
</a> </a>
<a class="{{if .PageIsSettingsDelete}}active{{end}} item" href="{{.OrgLink}}/settings/delete"> <a class="{{if .PageIsSettingsDelete}}active {{end}} item" href="{{.OrgLink}}/settings/delete">
{{.locale.Tr "org.settings.delete"}} {{.locale.Tr "org.settings.delete"}}
</a> </a>
</div> </div>

View File

@ -99,17 +99,17 @@
</td> </td>
<td class="center aligned"> <td class="center aligned">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="0"{{if or ($unit.Type.UnitGlobalDisabled) (eq ($.Team.UnitAccessMode $unit.Type) 0)}} checked{{end}}> <input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="0"{{if or ($unit.Type.UnitGlobalDisabled) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 0)}} checked{{end}}>
</div> </div>
</td> </td>
<td class="center aligned"> <td class="center aligned">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}> <input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
</div> </div>
</td> </td>
<td class="center aligned"> <td class="center aligned">
<div class="ui radio checkbox"> <div class="ui radio checkbox">
<input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="2"{{if (eq ($.Team.UnitAccessMode $unit.Type) 2)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}> <input type="radio" class="hidden" name="unit_{{$unit.Type.Value}}" value="2"{{if (eq ($.Team.UnitAccessMode $.Context $unit.Type) 2)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
</div> </div>
</td> </td>
</tr> </tr>
@ -121,7 +121,7 @@
{{if lt $unit.MaxPerm 2}} {{if lt $unit.MaxPerm 2}}
<div {{if $unit.Type.UnitGlobalDisabled}}class="field tooltip" data-content="{{$.locale.Tr "repo.unit_disabled"}}"{{else}}class="field"{{end}}> <div {{if $unit.Type.UnitGlobalDisabled}}class="field tooltip" data-content="{{$.locale.Tr "repo.unit_disabled"}}"{{else}}class="field"{{end}}>
<div class="ui checkbox"> <div class="ui checkbox">
<input type="checkbox" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}> <input type="checkbox" class="hidden" name="unit_{{$unit.Type.Value}}" value="1"{{if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 1)}} checked{{end}} {{if $unit.Type.UnitGlobalDisabled}}disabled{{end}}>
<label>{{$.locale.Tr $unit.NameKey}}{{if $unit.Type.UnitGlobalDisabled}} {{$.locale.Tr "org.team_unit_disabled"}}{{end}}</label> <label>{{$.locale.Tr $unit.NameKey}}{{if $unit.Type.UnitGlobalDisabled}} {{$.locale.Tr "org.team_unit_disabled"}}{{end}}</label>
<span class="help">{{$.locale.Tr $unit.DescKey}}</span> <span class="help">{{$.locale.Tr $unit.DescKey}}</span>
</div> </div>

View File

@ -61,11 +61,11 @@
{{if and (lt $unit.MaxPerm 2) (not $unit.Type.UnitGlobalDisabled)}} {{if and (lt $unit.MaxPerm 2) (not $unit.Type.UnitGlobalDisabled)}}
<tr> <tr>
<td><strong>{{$.locale.Tr $unit.NameKey}}</strong></td> <td><strong>{{$.locale.Tr $unit.NameKey}}</strong></td>
<td>{{if eq ($.Team.UnitAccessMode $unit.Type) 0 -}} <td>{{if eq ($.Team.UnitAccessMode $.Context $unit.Type) 0 -}}
{{$.locale.Tr "org.teams.none_access"}} {{$.locale.Tr "org.teams.none_access"}}
{{- else if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $unit.Type) 1) -}} {{- else if or (eq $.Team.ID 0) (eq ($.Team.UnitAccessMode $.Context $unit.Type) 1) -}}
{{$.locale.Tr "org.teams.read_access"}} {{$.locale.Tr "org.teams.read_access"}}
{{- else if eq ($.Team.UnitAccessMode $unit.Type) 2 -}} {{- else if eq ($.Team.UnitAccessMode $.Context $unit.Type) 2 -}}
{{$.locale.Tr "org.teams.write_access"}} {{$.locale.Tr "org.teams.write_access"}}
{{- end}}</td> {{- end}}</td>
</tr> </tr>

View File

@ -54,7 +54,7 @@
<span class="no-content">{{$.root.locale.Tr "repo.issues.no_content"}}</span> <span class="no-content">{{$.root.locale.Tr "repo.issues.no_content"}}</span>
{{end}} {{end}}
</div> </div>
<div id="comment-{{.ID}}" class="raw-content hide">{{.Content}}</div> <div id="issuecomment-{{.ID}}-raw" class="raw-content hide">{{.Content}}</div>
<div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.root.RepoLink}}/comments/{{.ID}}" data-context="{{$.root.RepoLink}}"></div> <div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.root.RepoLink}}/comments/{{.ID}}" data-context="{{$.root.RepoLink}}"></div>
</div> </div>
{{$reactions := .Reactions.GroupByType}} {{$reactions := .Reactions.GroupByType}}

View File

@ -40,8 +40,8 @@
</div> </div>
</div> </div>
<div class="field"> <div class="field">
{{$pullRequestEnabled := .Repository.UnitEnabled $.UnitTypePullRequests}} {{$pullRequestEnabled := .Repository.UnitEnabled $.Context $.UnitTypePullRequests}}
{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}} {{$prUnit := .Repository.MustGetUnit $.Context $.UnitTypePullRequests}}
<div class="ui radio checkbox"> <div class="ui radio checkbox">
{{if $pullRequestEnabled}} {{if $pullRequestEnabled}}
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{.locale.Tr "repo.editor.propose_file_change"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}> <input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{.locale.Tr "repo.editor.propose_file_change"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>

View File

@ -37,7 +37,7 @@
{{if eq $refGroup "pull"}} {{if eq $refGroup "pull"}}
{{if or (not $.HidePRRefs) (containGeneric $.SelectedBranches .Name)}} {{if or (not $.HidePRRefs) (containGeneric $.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 icon button basic tiny mr-2" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.UnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}"> <a class="ui labelled icon button basic tiny mr-2" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.Context $.UnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}">
{{svg "octicon-git-pull-request" 16 "mr-2"}}#{{.ShortName}} {{svg "octicon-git-pull-request" 16 "mr-2"}}#{{.ShortName}}
</a> </a>
{{end}} {{end}}

View File

@ -154,13 +154,13 @@
{{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}} {{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}}
<div class="ui tabular stackable menu navbar"> <div class="ui tabular stackable menu navbar">
{{if .Permission.CanRead $.UnitTypeCode}} {{if .Permission.CanRead $.UnitTypeCode}}
<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}"> <a class="{{if .PageIsViewCode}}active {{end}}item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}">
{{svg "octicon-code"}} {{.locale.Tr "repo.code"}} {{svg "octicon-code"}} {{.locale.Tr "repo.code"}}
</a> </a>
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeIssues}} {{if .Permission.CanRead $.UnitTypeIssues}}
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues"> <a class="{{if .PageIsIssueList}}active {{end}}item" href="{{.RepoLink}}/issues">
{{svg "octicon-issue-opened"}} {{.locale.Tr "repo.issues"}} {{svg "octicon-issue-opened"}} {{.locale.Tr "repo.issues"}}
{{if .Repository.NumOpenIssues}} {{if .Repository.NumOpenIssues}}
<span class="ui primary small label">{{CountFmt .Repository.NumOpenIssues}}</span> <span class="ui primary small label">{{CountFmt .Repository.NumOpenIssues}}</span>
@ -169,13 +169,13 @@
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypeExternalTracker}} {{if .Permission.CanRead $.UnitTypeExternalTracker}}
<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"}} {{.locale.Tr "repo.issues"}} </span> {{svg "octicon-link-external"}} {{.locale.Tr "repo.issues"}} </span>
</a> </a>
{{end}} {{end}}
{{if and .Repository.CanEnablePulls (.Permission.CanRead $.UnitTypePullRequests)}} {{if and .Repository.CanEnablePulls (.Permission.CanRead $.UnitTypePullRequests)}}
<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"}} {{.locale.Tr "repo.pulls"}} {{svg "octicon-git-pull-request"}} {{.locale.Tr "repo.pulls"}}
{{if .Repository.NumOpenPulls}} {{if .Repository.NumOpenPulls}}
<span class="ui primary small label">{{CountFmt .Repository.NumOpenPulls}}</span> <span class="ui primary small label">{{CountFmt .Repository.NumOpenPulls}}</span>
@ -193,13 +193,13 @@
{{end}} {{end}}
{{if .Permission.CanRead $.UnitTypePackages}} {{if .Permission.CanRead $.UnitTypePackages}}
<a href="{{.RepoLink}}/packages" class="{{if .IsPackagesPage}}active{{end}} item"> <a href="{{.RepoLink}}/packages" class="{{if .IsPackagesPage}}active {{end}}item">
{{svg "octicon-package"}} {{.locale.Tr "packages.title"}} {{svg "octicon-package"}} {{.locale.Tr "packages.title"}}
</a> </a>
{{end}} {{end}}
{{if and (not .UnitProjectsGlobalDisabled) (.Permission.CanRead $.UnitTypeProjects)}} {{if and (not .UnitProjectsGlobalDisabled) (.Permission.CanRead $.UnitTypeProjects)}}
<a href="{{.RepoLink}}/projects" class="{{if .IsProjectsPage}}active{{end}} item"> <a href="{{.RepoLink}}/projects" class="{{if .IsProjectsPage}}active {{end}}item">
{{svg "octicon-project"}} {{.locale.Tr "repo.project_board"}} {{svg "octicon-project"}} {{.locale.Tr "repo.project_board"}}
{{if .Repository.NumOpenProjects}} {{if .Repository.NumOpenProjects}}
<span class="ui primary small label">{{CountFmt .Repository.NumOpenProjects}}</span> <span class="ui primary small label">{{CountFmt .Repository.NumOpenProjects}}</span>
@ -208,7 +208,7 @@
{{end}} {{end}}
{{if and (.Permission.CanRead $.UnitTypeReleases) (not .IsEmptyRepo)}} {{if and (.Permission.CanRead $.UnitTypeReleases) (not .IsEmptyRepo)}}
<a class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases"> <a class="{{if .PageIsReleaseList}}active {{end}}item" href="{{.RepoLink}}/releases">
{{svg "octicon-tag"}} {{.locale.Tr "repo.releases"}} {{svg "octicon-tag"}} {{.locale.Tr "repo.releases"}}
{{if .NumReleases}} {{if .NumReleases}}
<span class="ui primary small label">{{CountFmt .NumReleases}}</span> <span class="ui primary small label">{{CountFmt .NumReleases}}</span>
@ -217,13 +217,13 @@
{{end}} {{end}}
{{if or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki)}} {{if or (.Permission.CanRead $.UnitTypeWiki) (.Permission.CanRead $.UnitTypeExternalWiki)}}
<a class="{{if .PageIsWiki}}active{{end}} item" href="{{.RepoLink}}/wiki" {{if and (.Permission.CanRead $.UnitTypeExternalWiki) (not (HasPrefix ((.Repository.MustGetUnit $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL) (.Repository.HTMLURL)))}} target="_blank" rel="noopener noreferrer" {{end}}> <a class="{{if .PageIsWiki}}active {{end}}item" href="{{.RepoLink}}/wiki" {{if and (.Permission.CanRead $.UnitTypeExternalWiki) (not (HasPrefix ((.Repository.MustGetUnit $.Context $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL) (.Repository.HTMLURL)))}} target="_blank" rel="noopener noreferrer" {{end}}>
{{svg "octicon-book"}} {{.locale.Tr "repo.wiki"}} {{svg "octicon-book"}} {{.locale.Tr "repo.wiki"}}
</a> </a>
{{end}} {{end}}
{{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (not .IsEmptyRepo)}} {{if and (.Permission.CanReadAny $.UnitTypePullRequests $.UnitTypeIssues $.UnitTypeReleases) (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"}} {{.locale.Tr "repo.activity"}} {{svg "octicon-pulse"}} {{.locale.Tr "repo.activity"}}
</a> </a>
{{end}} {{end}}
@ -232,7 +232,7 @@
{{if .Permission.IsAdmin}} {{if .Permission.IsAdmin}}
<div class="right menu"> <div class="right menu">
<a class="{{if .PageIsSettings}}active{{end}} item" href="{{.RepoLink}}/settings"> <a class="{{if .PageIsSettings}}active {{end}}item" href="{{.RepoLink}}/settings">
{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}} {{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}}
</a> </a>
</div> </div>
@ -241,7 +241,7 @@
{{else if .Permission.IsAdmin}} {{else if .Permission.IsAdmin}}
<div class="ui tabular stackable menu navbar"> <div class="ui tabular stackable menu navbar">
<div class="right menu"> <div class="right menu">
<a class="{{if .PageIsSettings}}active{{end}} item" href="{{.RepoLink}}/settings"> <a class="{{if .PageIsSettings}}active {{end}}item" href="{{.RepoLink}}/settings">
{{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}} {{svg "octicon-tools"}} {{.locale.Tr "repo.settings"}}
</a> </a>
</div> </div>

View File

@ -9,10 +9,10 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "alphabetically") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&state={{$.State}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> <a class="{{if or (eq .SortType "alphabetically") (not .SortType)}}active {{end}}item" href="{{$.Link}}?sort=alphabetically&state={{$.State}}">{{.locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a>
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&state={{$.State}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="{{$.Link}}?sort=reversealphabetically&state={{$.State}}">{{.locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a>
<a class="{{if eq .SortType "leastissues"}}active{{end}} item" href="{{$.Link}}?sort=leastissues&state={{$.State}}">{{.locale.Tr "repo.milestones.filter_sort.least_issues"}}</a> <a class="{{if eq .SortType "leastissues"}}active {{end}}item" href="{{$.Link}}?sort=leastissues&state={{$.State}}">{{.locale.Tr "repo.milestones.filter_sort.least_issues"}}</a>
<a class="{{if eq .SortType "mostissues"}}active{{end}} item" href="{{$.Link}}?sort=mostissues&state={{$.State}}">{{.locale.Tr "repo.milestones.filter_sort.most_issues"}}</a> <a class="{{if eq .SortType "mostissues"}}active {{end}}item" href="{{$.Link}}?sort=mostissues&state={{$.State}}">{{.locale.Tr "repo.milestones.filter_sort.most_issues"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -123,12 +123,12 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if eq .ViewType "all"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=all&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.all_issues"}}</a> <a class="{{if eq .ViewType "all"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=all&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.all_issues"}}</a>
<a class="{{if eq .ViewType "assigned"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=assigned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.assigned_to_you"}}</a> <a class="{{if eq .ViewType "assigned"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=assigned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.assigned_to_you"}}</a>
<a class="{{if eq .ViewType "created_by"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=created_by&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.created_by_you"}}</a> <a class="{{if eq .ViewType "created_by"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=created_by&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.created_by_you"}}</a>
<a class="{{if eq .ViewType "mentioned"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=mentioned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.mentioning_you"}}</a> <a class="{{if eq .ViewType "mentioned"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=mentioned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.mentioning_you"}}</a>
{{if .PageIsPullList}} {{if .PageIsPullList}}
<a class="{{if eq .ViewType "review_requested"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=review_requested&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.review_requested"}}</a> <a class="{{if eq .ViewType "review_requested"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=review_requested&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.review_requested"}}</a>
{{end}} {{end}}
</div> </div>
</div> </div>
@ -141,14 +141,14 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=latest&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a> <a class="{{if or (eq .SortType "latest") (not .SortType)}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=latest&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=oldest&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a> <a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=oldest&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a> <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a> <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.mostcomment"}}</a> <a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastcomment"}}</a> <a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
<a class="{{if eq .SortType "nearduedate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=nearduedate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.nearduedate"}}</a> <a class="{{if eq .SortType "nearduedate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=nearduedate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.nearduedate"}}</a>
<a class="{{if eq .SortType "farduedate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=farduedate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.farduedate"}}</a> <a class="{{if eq .SortType "farduedate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=farduedate&state={{$.State}}&labels={{.SelectLabels}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.farduedate"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -108,11 +108,11 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if eq .ViewType "all"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=all&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.all_issues"}}</a> <a class="{{if eq .ViewType "all"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=all&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.all_issues"}}</a>
<a class="{{if eq .ViewType "assigned"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=assigned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.assigned_to_you"}}</a> <a class="{{if eq .ViewType "assigned"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=assigned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.assigned_to_you"}}</a>
<a class="{{if eq .ViewType "created_by"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=created_by&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.created_by_you"}}</a> <a class="{{if eq .ViewType "created_by"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=created_by&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.created_by_you"}}</a>
<a class="{{if eq .ViewType "mentioned"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=mentioned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.mentioning_you"}}</a> <a class="{{if eq .ViewType "mentioned"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=mentioned&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.mentioning_you"}}</a>
<a class="{{if eq .ViewType "review_requested"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type=review_requested&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.review_requested"}}</a> <a class="{{if eq .ViewType "review_requested"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type=review_requested&sort={{$.SortType}}&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_type.review_requested"}}</a>
</div> </div>
</div> </div>
{{end}} {{end}}
@ -124,12 +124,12 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "latest") (not .SortType)}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=latest&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a> <a class="{{if or (eq .SortType "latest") (not .SortType)}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=latest&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.latest"}}</a>
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=oldest&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a> <a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=oldest&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a> <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=recentupdate&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a> <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastupdate&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<a class="{{if eq .SortType "mostcomment"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.mostcomment"}}</a> <a class="{{if eq .SortType "mostcomment"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=mostcomment&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.mostcomment"}}</a>
<a class="{{if eq .SortType "leastcomment"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastcomment"}}</a> <a class="{{if eq .SortType "leastcomment"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort=leastcomment&state={{$.State}}&labels={{.SelectLabels}}&assignee={{$.AssigneeID}}&poster={{$.PosterID}}">{{.locale.Tr "repo.issues.filter_sort.leastcomment"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -46,12 +46,12 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span> </span>
<div class="menu"> <div class="menu">
<a class="{{if or (eq .SortType "closestduedate") (not .SortType)}}active{{end}} item" href="{{$.Link}}?sort=closestduedate&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.closest_due_date"}}</a> <a class="{{if or (eq .SortType "closestduedate") (not .SortType)}}active {{end}}item" href="{{$.Link}}?sort=closestduedate&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.closest_due_date"}}</a>
<a class="{{if eq .SortType "furthestduedate"}}active{{end}} item" href="{{$.Link}}?sort=furthestduedate&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.furthest_due_date"}}</a> <a class="{{if eq .SortType "furthestduedate"}}active {{end}}item" href="{{$.Link}}?sort=furthestduedate&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.furthest_due_date"}}</a>
<a class="{{if eq .SortType "leastcomplete"}}active{{end}} item" href="{{$.Link}}?sort=leastcomplete&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.least_complete"}}</a> <a class="{{if eq .SortType "leastcomplete"}}active {{end}}item" href="{{$.Link}}?sort=leastcomplete&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.least_complete"}}</a>
<a class="{{if eq .SortType "mostcomplete"}}active{{end}} item" href="{{$.Link}}?sort=mostcomplete&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.most_complete"}}</a> <a class="{{if eq .SortType "mostcomplete"}}active {{end}}item" href="{{$.Link}}?sort=mostcomplete&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.most_complete"}}</a>
<a class="{{if eq .SortType "mostissues"}}active{{end}} item" href="{{$.Link}}?sort=mostissues&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.most_issues"}}</a> <a class="{{if eq .SortType "mostissues"}}active {{end}}item" href="{{$.Link}}?sort=mostissues&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.most_issues"}}</a>
<a class="{{if eq .SortType "leastissues"}}active{{end}} item" href="{{$.Link}}?sort=leastissues&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.least_issues"}}</a> <a class="{{if eq .SortType "leastissues"}}active {{end}}item" href="{{$.Link}}?sort=leastissues&state={{$.State}}&q={{$.Keyword}}">{{.locale.Tr "repo.milestones.filter_sort.least_issues"}}</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
<div class="ui compact left small menu"> <div class="ui compact left small menu">
<a class="{{if .PageIsLabels}}active{{end}} item" href="{{.RepoLink}}/labels">{{.locale.Tr "repo.labels"}}</a> <a class="{{if .PageIsLabels}}active {{end}}item" href="{{.RepoLink}}/labels">{{.locale.Tr "repo.labels"}}</a>
<a class="{{if .PageIsMilestones}}active{{end}} item" href="{{.RepoLink}}/milestones">{{.locale.Tr "repo.milestones"}}</a> <a class="{{if .PageIsMilestones}}active {{end}}item" href="{{.RepoLink}}/milestones">{{.locale.Tr "repo.milestones"}}</a>
</div> </div>

View File

@ -1,5 +1,5 @@
<div class="ui compact tiny menu"> <div class="ui compact tiny menu">
<a class="{{if not .IsShowClosed}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}"> <a class="{{if not .IsShowClosed}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}">
{{if .PageIsPullList}} {{if .PageIsPullList}}
{{svg "octicon-git-pull-request" 16 "mr-3"}} {{svg "octicon-git-pull-request" 16 "mr-3"}}
{{else}} {{else}}
@ -7,7 +7,7 @@
{{end}} {{end}}
{{JsPrettyNumber .IssueStats.OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}} {{JsPrettyNumber .IssueStats.OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
</a> </a>
<a class="{{if .IsShowClosed}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&type={{.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}"> <a class="{{if .IsShowClosed}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{.ViewType}}&sort={{$.SortType}}&state=closed&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}">
{{svg "octicon-check" 16 "mr-3"}} {{svg "octicon-check" 16 "mr-3"}}
{{JsPrettyNumber .IssueStats.ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}} {{JsPrettyNumber .IssueStats.ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
</a> </a>

View File

@ -77,7 +77,7 @@
<span class="no-content">{{.locale.Tr "repo.issues.no_content"}}</span> <span class="no-content">{{.locale.Tr "repo.issues.no_content"}}</span>
{{end}} {{end}}
</div> </div>
<div id="comment-{{.Issue.ID}}" class="raw-content hide">{{.Issue.Content}}</div> <div id="issue-{{.Issue.ID}}-raw" class="raw-content hide">{{.Issue.Content}}</div>
<div class="edit-content-zone hide" data-write="issue-{{.Issue.ID}}-write" data-preview="issue-{{.Issue.ID}}-preview" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/content" data-context="{{.RepoLink}}" data-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/attachments" data-view-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/view-attachments"></div> <div class="edit-content-zone hide" data-write="issue-{{.Issue.ID}}-write" data-preview="issue-{{.Issue.ID}}-preview" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/content" data-context="{{.RepoLink}}" data-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/attachments" data-view-attachment-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/view-attachments"></div>
{{if .Issue.Attachments}} {{if .Issue.Attachments}}
{{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Issue.Attachments "Content" .Issue.RenderedContent}} {{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Issue.Attachments "Content" .Issue.RenderedContent}}

View File

@ -77,7 +77,7 @@
<span class="no-content">{{$.locale.Tr "repo.issues.no_content"}}</span> <span class="no-content">{{$.locale.Tr "repo.issues.no_content"}}</span>
{{end}} {{end}}
</div> </div>
<div id="comment-{{.ID}}" class="raw-content hide">{{.Content}}</div> <div id="issuecomment-{{.ID}}-raw" class="raw-content hide">{{.Content}}</div>
<div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div> <div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}} {{if .Attachments}}
{{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Attachments "Content" .RenderedContent}} {{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Attachments "Content" .RenderedContent}}
@ -449,7 +449,7 @@
<span class="no-content">{{$.locale.Tr "repo.issues.no_content"}}</span> <span class="no-content">{{$.locale.Tr "repo.issues.no_content"}}</span>
{{end}} {{end}}
</div> </div>
<div id="comment-{{.ID}}" class="raw-content hide">{{.Content}}</div> <div id="issuecomment-{{.ID}}-raw" class="raw-content hide">{{.Content}}</div>
<div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div> <div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
{{if .Attachments}} {{if .Attachments}}
{{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Attachments "Content" .RenderedContent}} {{template "repo/issue/view_content/attachments" Dict "ctx" $ "Attachments" .Attachments "Content" .RenderedContent}}
@ -576,7 +576,7 @@
<span class="no-content">{{$.locale.Tr "repo.issues.no_content"}}</span> <span class="no-content">{{$.locale.Tr "repo.issues.no_content"}}</span>
{{end}} {{end}}
</div> </div>
<div id="comment-{{.ID}}" class="raw-content hide">{{.Content}}</div> <div id="issuecomment-{{.ID}}-raw" class="raw-content hide">{{.Content}}</div>
<div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div> <div class="edit-content-zone hide" data-write="issuecomment-{{.ID}}-write" data-preview="issuecomment-{{.ID}}-preview" data-update-url="{{$.RepoLink}}/comments/{{.ID}}" data-context="{{$.RepoLink}}" data-attachment-url="{{$.RepoLink}}/comments/{{.ID}}/attachments"></div>
</div> </div>
{{$reactions := .Reactions.GroupByType}} {{$reactions := .Reactions.GroupByType}}

View File

@ -11,9 +11,9 @@
{{$referenceUrl = Printf "%s/files#%s" .ctx.Issue.HTMLURL .item.HashTag}} {{$referenceUrl = Printf "%s/files#%s" .ctx.Issue.HTMLURL .item.HashTag}}
{{end}} {{end}}
<div class="item context" data-clipboard-text="{{$referenceUrl}}">{{.ctx.locale.Tr "repo.issues.context.copy_link"}}</div> <div class="item context" data-clipboard-text="{{$referenceUrl}}">{{.ctx.locale.Tr "repo.issues.context.copy_link"}}</div>
<div class="item context quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.ID}}">{{.ctx.locale.Tr "repo.issues.context.quote_reply"}}</div> <div class="item context quote-reply {{if .diff}}quote-reply-diff{{end}}" data-target="{{.item.HashTag}}-raw">{{.ctx.locale.Tr "repo.issues.context.quote_reply"}}</div>
{{if not .ctx.UnitIssuesGlobalDisabled}} {{if not .ctx.UnitIssuesGlobalDisabled}}
<div class="item context reference-issue" data-target="{{.item.ID}}" data-modal="#reference-issue-modal" data-poster="{{.item.Poster.GetDisplayName}}" data-poster-username="{{.item.Poster.Name}}" data-reference="{{$referenceUrl}}">{{.ctx.locale.Tr "repo.issues.context.reference_issue"}}</div> <div class="item context reference-issue" data-target="{{.item.HashTag}}-raw" data-modal="#reference-issue-modal" data-poster="{{.item.Poster.GetDisplayName}}" data-poster-username="{{.item.Poster.Name}}" data-reference="{{$referenceUrl}}">{{.ctx.locale.Tr "repo.issues.context.reference_issue"}}</div>
{{end}} {{end}}
{{if or .ctx.Permission.IsAdmin .IsCommentPoster .ctx.HasIssuesOrPullsWritePermission}} {{if or .ctx.Permission.IsAdmin .IsCommentPoster .ctx.HasIssuesOrPullsWritePermission}}
<div class="divider"></div> <div class="divider"></div>

Some files were not shown because too many files have changed in this diff Show More