Move attachment into models/repo/ (#17650)
* Move attachment into models/repo/ * Fix test * Fix bug
This commit is contained in:
parent
7a03473159
commit
fc3d082609
39 changed files with 477 additions and 414 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/migrations"
|
"code.gitea.io/gitea/models/migrations"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
|
@ -79,7 +80,7 @@ var CmdMigrateStorage = cli.Command{
|
||||||
}
|
}
|
||||||
|
|
||||||
func migrateAttachments(dstStorage storage.ObjectStorage) error {
|
func migrateAttachments(dstStorage storage.ObjectStorage) error {
|
||||||
return models.IterateAttachment(func(attach *models.Attachment) error {
|
return repo_model.IterateAttachment(func(attach *repo_model.Attachment) error {
|
||||||
_, err := storage.Copy(dstStorage, attach.RelativePath(), storage.Attachments, attach.RelativePath())
|
_, err := storage.Copy(dstStorage, attach.RelativePath(), storage.Attachments, attach.RelativePath())
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/test"
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ func TestGetAttachment(t *testing.T) {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
//Write empty file to be available for response
|
//Write empty file to be available for response
|
||||||
if tc.createFile {
|
if tc.createFile {
|
||||||
_, err := storage.Attachments.Save(models.AttachmentRelativePath(tc.uuid), strings.NewReader("hello world"), -1)
|
_, err := storage.Attachments.Save(repo_model.AttachmentRelativePath(tc.uuid), strings.NewReader("hello world"), -1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
//Actual test
|
//Actual test
|
||||||
|
|
|
@ -1679,29 +1679,6 @@ func (err ErrMilestoneNotExist) Error() string {
|
||||||
return fmt.Sprintf("milestone does not exist [id: %d, repo_id: %d]", err.ID, err.RepoID)
|
return fmt.Sprintf("milestone does not exist [id: %d, repo_id: %d]", err.ID, err.RepoID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// _____ __ __ .__ __
|
|
||||||
// / _ \_/ |__/ |______ ____ | |__ _____ ____ _____/ |_
|
|
||||||
// / /_\ \ __\ __\__ \ _/ ___\| | \ / \_/ __ \ / \ __\
|
|
||||||
// / | \ | | | / __ \\ \___| Y \ Y Y \ ___/| | \ |
|
|
||||||
// \____|__ /__| |__| (____ /\___ >___| /__|_| /\___ >___| /__|
|
|
||||||
// \/ \/ \/ \/ \/ \/ \/
|
|
||||||
|
|
||||||
// ErrAttachmentNotExist represents a "AttachmentNotExist" kind of error.
|
|
||||||
type ErrAttachmentNotExist struct {
|
|
||||||
ID int64
|
|
||||||
UUID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsErrAttachmentNotExist checks if an error is a ErrAttachmentNotExist.
|
|
||||||
func IsErrAttachmentNotExist(err error) bool {
|
|
||||||
_, ok := err.(ErrAttachmentNotExist)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err ErrAttachmentNotExist) Error() string {
|
|
||||||
return fmt.Sprintf("attachment does not exist [id: %d, uuid: %s]", err.ID, err.UUID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ___________
|
// ___________
|
||||||
// \__ ___/___ _____ _____
|
// \__ ___/___ _____ _____
|
||||||
// | |_/ __ \\__ \ / \
|
// | |_/ __ \\__ \ / \
|
||||||
|
@ -1758,7 +1735,7 @@ type ErrUploadNotExist struct {
|
||||||
|
|
||||||
// IsErrUploadNotExist checks if an error is a ErrUploadNotExist.
|
// IsErrUploadNotExist checks if an error is a ErrUploadNotExist.
|
||||||
func IsErrUploadNotExist(err error) bool {
|
func IsErrUploadNotExist(err error) bool {
|
||||||
_, ok := err.(ErrAttachmentNotExist)
|
_, ok := err.(ErrUploadNotExist)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
108
models/issue.go
108
models/issue.go
|
@ -15,6 +15,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/issues"
|
"code.gitea.io/gitea/models/issues"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -60,7 +61,7 @@ type Issue struct {
|
||||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||||
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"`
|
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"`
|
||||||
|
|
||||||
Attachments []*Attachment `xorm:"-"`
|
Attachments []*repo_model.Attachment `xorm:"-"`
|
||||||
Comments []*Comment `xorm:"-"`
|
Comments []*Comment `xorm:"-"`
|
||||||
Reactions ReactionList `xorm:"-"`
|
Reactions ReactionList `xorm:"-"`
|
||||||
TotalTrackedTime int64 `xorm:"-"`
|
TotalTrackedTime int64 `xorm:"-"`
|
||||||
|
@ -273,7 +274,8 @@ func (issue *Issue) loadMilestone(e db.Engine) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) loadAttributes(e db.Engine) (err error) {
|
func (issue *Issue) loadAttributes(ctx context.Context) (err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
if err = issue.loadRepo(e); err != nil {
|
if err = issue.loadRepo(e); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -304,7 +306,7 @@ func (issue *Issue) loadAttributes(e db.Engine) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.Attachments == nil {
|
if issue.Attachments == nil {
|
||||||
issue.Attachments, err = getAttachmentsByIssueID(e, issue.ID)
|
issue.Attachments, err = repo_model.GetAttachmentsByIssueIDCtx(ctx, issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getAttachmentsByIssueID [%d]: %v", issue.ID, err)
|
return fmt.Errorf("getAttachmentsByIssueID [%d]: %v", issue.ID, err)
|
||||||
}
|
}
|
||||||
|
@ -328,7 +330,7 @@ func (issue *Issue) loadAttributes(e db.Engine) (err error) {
|
||||||
|
|
||||||
// LoadAttributes loads the attribute of this issue.
|
// LoadAttributes loads the attribute of this issue.
|
||||||
func (issue *Issue) LoadAttributes() error {
|
func (issue *Issue) LoadAttributes() error {
|
||||||
return issue.loadAttributes(db.GetEngine(db.DefaultContext))
|
return issue.loadAttributes(db.DefaultContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadMilestone load milestone of this issue.
|
// LoadMilestone load milestone of this issue.
|
||||||
|
@ -426,12 +428,12 @@ func (issue *Issue) HasLabel(labelID int64) bool {
|
||||||
return issue.hasLabel(db.GetEngine(db.DefaultContext), labelID)
|
return issue.hasLabel(db.GetEngine(db.DefaultContext), labelID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) addLabel(e db.Engine, label *Label, doer *User) error {
|
func (issue *Issue) addLabel(ctx context.Context, label *Label, doer *User) error {
|
||||||
return newIssueLabel(e, issue, label, doer)
|
return newIssueLabel(ctx, issue, label, doer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) addLabels(e db.Engine, labels []*Label, doer *User) error {
|
func (issue *Issue) addLabels(ctx context.Context, labels []*Label, doer *User) error {
|
||||||
return newIssueLabels(e, issue, labels, doer)
|
return newIssueLabels(ctx, issue, labels, doer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) getLabels(e db.Engine) (err error) {
|
func (issue *Issue) getLabels(e db.Engine) (err error) {
|
||||||
|
@ -446,17 +448,17 @@ func (issue *Issue) getLabels(e db.Engine) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) removeLabel(e db.Engine, doer *User, label *Label) error {
|
func (issue *Issue) removeLabel(ctx context.Context, doer *User, label *Label) error {
|
||||||
return deleteIssueLabel(e, issue, label, doer)
|
return deleteIssueLabel(ctx, issue, label, doer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) clearLabels(e db.Engine, doer *User) (err error) {
|
func (issue *Issue) clearLabels(ctx context.Context, doer *User) (err error) {
|
||||||
if err = issue.getLabels(e); err != nil {
|
if err = issue.getLabels(db.GetEngine(ctx)); err != nil {
|
||||||
return fmt.Errorf("getLabels: %v", err)
|
return fmt.Errorf("getLabels: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range issue.Labels {
|
for i := range issue.Labels {
|
||||||
if err = issue.removeLabel(e, doer, issue.Labels[i]); err != nil {
|
if err = issue.removeLabel(ctx, doer, issue.Labels[i]); err != nil {
|
||||||
return fmt.Errorf("removeLabel: %v", err)
|
return fmt.Errorf("removeLabel: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -487,7 +489,7 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
|
||||||
return ErrRepoLabelNotExist{}
|
return ErrRepoLabelNotExist{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.clearLabels(db.GetEngine(ctx), doer); err != nil {
|
if err = issue.clearLabels(ctx, doer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,13 +563,13 @@ func (issue *Issue) ReplaceLabels(labels []*Label, doer *User) (err error) {
|
||||||
toRemove = append(toRemove, issue.Labels[removeIndex:]...)
|
toRemove = append(toRemove, issue.Labels[removeIndex:]...)
|
||||||
|
|
||||||
if len(toAdd) > 0 {
|
if len(toAdd) > 0 {
|
||||||
if err = issue.addLabels(db.GetEngine(ctx), toAdd, doer); err != nil {
|
if err = issue.addLabels(ctx, toAdd, doer); err != nil {
|
||||||
return fmt.Errorf("addLabels: %v", err)
|
return fmt.Errorf("addLabels: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, l := range toRemove {
|
for _, l := range toRemove {
|
||||||
if err = issue.removeLabel(db.GetEngine(ctx), doer, l); err != nil {
|
if err = issue.removeLabel(ctx, doer, l); err != nil {
|
||||||
return fmt.Errorf("removeLabel: %v", err)
|
return fmt.Errorf("removeLabel: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -596,9 +598,9 @@ func updateIssueCols(e db.Engine, issue *Issue, cols ...string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) changeStatus(e db.Engine, doer *User, isClosed, isMergePull bool) (*Comment, error) {
|
func (issue *Issue) changeStatus(ctx context.Context, doer *User, isClosed, isMergePull bool) (*Comment, error) {
|
||||||
// Reload the issue
|
// Reload the issue
|
||||||
currentIssue, err := getIssueByID(e, issue.ID)
|
currentIssue, err := getIssueByID(db.GetEngine(ctx), issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -616,10 +618,11 @@ func (issue *Issue) changeStatus(e db.Engine, doer *User, isClosed, isMergePull
|
||||||
}
|
}
|
||||||
|
|
||||||
issue.IsClosed = isClosed
|
issue.IsClosed = isClosed
|
||||||
return issue.doChangeStatus(e, doer, isMergePull)
|
return issue.doChangeStatus(ctx, doer, isMergePull)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) doChangeStatus(e db.Engine, doer *User, isMergePull bool) (*Comment, error) {
|
func (issue *Issue) doChangeStatus(ctx context.Context, doer *User, isMergePull bool) (*Comment, error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
// Check for open dependencies
|
// Check for open dependencies
|
||||||
if issue.IsClosed && issue.Repo.isDependenciesEnabled(e) {
|
if issue.IsClosed && issue.Repo.isDependenciesEnabled(e) {
|
||||||
// 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
|
||||||
|
@ -672,7 +675,7 @@ func (issue *Issue) doChangeStatus(e db.Engine, doer *User, isMergePull bool) (*
|
||||||
cmtType = CommentTypeMergePull
|
cmtType = CommentTypeMergePull
|
||||||
}
|
}
|
||||||
|
|
||||||
return createComment(e, &CreateCommentOptions{
|
return createComment(ctx, &CreateCommentOptions{
|
||||||
Type: cmtType,
|
Type: cmtType,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
@ -695,7 +698,7 @@ func (issue *Issue) ChangeStatus(doer *User, isClosed bool) (*Comment, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
comment, err := issue.changeStatus(db.GetEngine(ctx), doer, isClosed, false)
|
comment, err := issue.changeStatus(ctx, doer, isClosed, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -731,10 +734,10 @@ func (issue *Issue) ChangeTitle(doer *User, oldTitle string) (err error) {
|
||||||
OldTitle: oldTitle,
|
OldTitle: oldTitle,
|
||||||
NewTitle: issue.Title,
|
NewTitle: issue.Title,
|
||||||
}
|
}
|
||||||
if _, err = createComment(db.GetEngine(ctx), opts); err != nil {
|
if _, err = createComment(ctx, opts); err != nil {
|
||||||
return fmt.Errorf("createComment: %v", err)
|
return fmt.Errorf("createComment: %v", err)
|
||||||
}
|
}
|
||||||
if err = issue.addCrossReferences(db.GetEngine(ctx), doer, true); err != nil {
|
if err = issue.addCrossReferences(ctx, doer, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,7 +770,7 @@ func (issue *Issue) ChangeRef(doer *User, oldRef string) (err error) {
|
||||||
OldRef: oldRefFriendly,
|
OldRef: oldRefFriendly,
|
||||||
NewRef: newRefFriendly,
|
NewRef: newRefFriendly,
|
||||||
}
|
}
|
||||||
if _, err = createComment(db.GetEngine(ctx), opts); err != nil {
|
if _, err = createComment(ctx, opts); err != nil {
|
||||||
return fmt.Errorf("createComment: %v", err)
|
return fmt.Errorf("createComment: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -792,7 +795,7 @@ func AddDeletePRBranchComment(doer *User, repo *Repository, issueID int64, branc
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
OldRef: branchName,
|
OldRef: branchName,
|
||||||
}
|
}
|
||||||
if _, err = createComment(db.GetEngine(ctx), opts); err != nil {
|
if _, err = createComment(ctx, opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,13 +809,13 @@ func (issue *Issue) UpdateAttachments(uuids []string) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
attachments, err := getAttachmentsByUUIDs(db.GetEngine(ctx), uuids)
|
attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, uuids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", uuids, err)
|
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", uuids, err)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(attachments); i++ {
|
for i := 0; i < len(attachments); i++ {
|
||||||
attachments[i].IssueID = issue.ID
|
attachments[i].IssueID = issue.ID
|
||||||
if err := updateAttachment(db.GetEngine(ctx), attachments[i]); err != nil {
|
if err := repo_model.UpdateAttachmentCtx(ctx, attachments[i]); err != nil {
|
||||||
return fmt.Errorf("update attachment [id: %d]: %v", attachments[i].ID, err)
|
return fmt.Errorf("update attachment [id: %d]: %v", attachments[i].ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -838,7 +841,7 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
|
||||||
return fmt.Errorf("SaveIssueContentHistory: %v", err)
|
return fmt.Errorf("SaveIssueContentHistory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.addCrossReferences(ctx.Engine(), doer, true); err != nil {
|
if err = issue.addCrossReferences(ctx, doer, true); err != nil {
|
||||||
return fmt.Errorf("addCrossReferences: %v", err)
|
return fmt.Errorf("addCrossReferences: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,7 +911,8 @@ type NewIssueOptions struct {
|
||||||
IsPull bool
|
IsPull bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIssue(e db.Engine, doer *User, opts NewIssueOptions) (err error) {
|
func newIssue(ctx context.Context, doer *User, opts NewIssueOptions) (err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
opts.Issue.Title = strings.TrimSpace(opts.Issue.Title)
|
opts.Issue.Title = strings.TrimSpace(opts.Issue.Title)
|
||||||
|
|
||||||
if opts.Issue.MilestoneID > 0 {
|
if opts.Issue.MilestoneID > 0 {
|
||||||
|
@ -949,7 +953,7 @@ func newIssue(e db.Engine, doer *User, opts NewIssueOptions) (err error) {
|
||||||
OldMilestoneID: 0,
|
OldMilestoneID: 0,
|
||||||
MilestoneID: opts.Issue.MilestoneID,
|
MilestoneID: opts.Issue.MilestoneID,
|
||||||
}
|
}
|
||||||
if _, err = createComment(e, opts); err != nil {
|
if _, err = createComment(ctx, opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -981,7 +985,7 @@ func newIssue(e db.Engine, doer *User, opts NewIssueOptions) (err error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = opts.Issue.addLabel(e, label, opts.Issue.Poster); err != nil {
|
if err = opts.Issue.addLabel(ctx, label, opts.Issue.Poster); err != nil {
|
||||||
return fmt.Errorf("addLabel [id: %d]: %v", label.ID, err)
|
return fmt.Errorf("addLabel [id: %d]: %v", label.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -992,7 +996,7 @@ func newIssue(e db.Engine, doer *User, opts NewIssueOptions) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(opts.Attachments) > 0 {
|
if len(opts.Attachments) > 0 {
|
||||||
attachments, err := getAttachmentsByUUIDs(e, opts.Attachments)
|
attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, opts.Attachments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", opts.Attachments, err)
|
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", opts.Attachments, err)
|
||||||
}
|
}
|
||||||
|
@ -1004,7 +1008,7 @@ func newIssue(e db.Engine, doer *User, opts NewIssueOptions) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = opts.Issue.loadAttributes(e); err != nil {
|
if err = opts.Issue.loadAttributes(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1013,7 +1017,7 @@ func newIssue(e db.Engine, doer *User, opts NewIssueOptions) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return opts.Issue.addCrossReferences(e, doer, false)
|
return opts.Issue.addCrossReferences(ctx, doer, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecalculateIssueIndexForRepo create issue_index for repo if not exist and
|
// RecalculateIssueIndexForRepo create issue_index for repo if not exist and
|
||||||
|
@ -1056,7 +1060,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
if err = newIssue(db.GetEngine(ctx), issue.Poster, NewIssueOptions{
|
if err = newIssue(ctx, issue.Poster, NewIssueOptions{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: labelIDs,
|
||||||
|
@ -1119,7 +1123,7 @@ func GetIssueWithAttrsByID(id int64) (*Issue, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return issue, issue.loadAttributes(db.GetEngine(db.DefaultContext))
|
return issue, issue.loadAttributes(db.DefaultContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetIssueByID returns an issue by given ID.
|
// GetIssueByID returns an issue by given ID.
|
||||||
|
@ -1838,11 +1842,12 @@ func SearchIssueIDsByKeyword(kw string, repoIDs []int64, limit, start int) (int6
|
||||||
// If the issue status is changed a statusChangeComment is returned
|
// If the issue status is changed a statusChangeComment is returned
|
||||||
// similarly if the title is changed the titleChanged bool is set to true
|
// similarly if the title is changed the titleChanged bool is set to true
|
||||||
func UpdateIssueByAPI(issue *Issue, doer *User) (statusChangeComment *Comment, titleChanged bool, err error) {
|
func UpdateIssueByAPI(issue *Issue, doer *User) (statusChangeComment *Comment, titleChanged bool, err error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if err := issue.loadRepo(sess); err != nil {
|
if err := issue.loadRepo(sess); err != nil {
|
||||||
return nil, false, fmt.Errorf("loadRepo: %v", err)
|
return nil, false, fmt.Errorf("loadRepo: %v", err)
|
||||||
|
@ -1871,23 +1876,23 @@ func UpdateIssueByAPI(issue *Issue, doer *User) (statusChangeComment *Comment, t
|
||||||
OldTitle: currentIssue.Title,
|
OldTitle: currentIssue.Title,
|
||||||
NewTitle: issue.Title,
|
NewTitle: issue.Title,
|
||||||
}
|
}
|
||||||
_, err := createComment(sess, opts)
|
_, err := createComment(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("createComment: %v", err)
|
return nil, false, fmt.Errorf("createComment: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentIssue.IsClosed != issue.IsClosed {
|
if currentIssue.IsClosed != issue.IsClosed {
|
||||||
statusChangeComment, err = issue.doChangeStatus(sess, doer, false)
|
statusChangeComment, err = issue.doChangeStatus(ctx, doer, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := issue.addCrossReferences(sess, doer, true); err != nil {
|
if err := issue.addCrossReferences(ctx, doer, true); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
return statusChangeComment, titleChanged, sess.Commit()
|
return statusChangeComment, titleChanged, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it.
|
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it.
|
||||||
|
@ -1897,11 +1902,12 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *Us
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
// Update the deadline
|
// Update the deadline
|
||||||
if err = updateIssueCols(sess, &Issue{ID: issue.ID, DeadlineUnix: deadlineUnix}, "deadline_unix"); err != nil {
|
if err = updateIssueCols(sess, &Issue{ID: issue.ID, DeadlineUnix: deadlineUnix}, "deadline_unix"); err != nil {
|
||||||
|
@ -1909,11 +1915,11 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *Us
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the comment
|
// Make the comment
|
||||||
if _, err = createDeadlineComment(sess, doer, issue, deadlineUnix); err != nil {
|
if _, err = createDeadlineComment(ctx, doer, issue, deadlineUnix); err != nil {
|
||||||
return fmt.Errorf("createRemovedDueDateComment: %v", err)
|
return fmt.Errorf("createRemovedDueDateComment: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DependencyInfo represents high level information about an issue which is a dependency of another issue.
|
// DependencyInfo represents high level information about an issue which is a dependency of another issue.
|
||||||
|
@ -2244,7 +2250,7 @@ func deleteIssuesByRepoID(sess db.Engine, repoID int64) (attachmentPaths []strin
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var attachments []*Attachment
|
var attachments []*repo_model.Attachment
|
||||||
if err = sess.In("issue_id", deleteCond).
|
if err = sess.In("issue_id", deleteCond).
|
||||||
Find(&attachments); err != nil {
|
Find(&attachments); err != nil {
|
||||||
return
|
return
|
||||||
|
@ -2255,7 +2261,7 @@ func deleteIssuesByRepoID(sess db.Engine, repoID int64) (attachmentPaths []strin
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = sess.In("issue_id", deleteCond).
|
if _, err = sess.In("issue_id", deleteCond).
|
||||||
Delete(&Attachment{}); err != nil {
|
Delete(&repo_model.Attachment{}); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,11 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IssueAssignees saves all issue assignees
|
// IssueAssignees saves all issue assignees
|
||||||
|
@ -94,26 +93,26 @@ func clearAssigneeByUserID(sess db.Engine, userID int64) (err error) {
|
||||||
|
|
||||||
// ToggleAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
|
// ToggleAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
|
||||||
func (issue *Issue) ToggleAssignee(doer *User, assigneeID int64) (removed bool, comment *Comment, err error) {
|
func (issue *Issue) ToggleAssignee(doer *User, assigneeID int64) (removed bool, comment *Comment, err error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
|
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
removed, comment, err = issue.toggleAssignee(sess, doer, assigneeID, false)
|
removed, comment, err = issue.toggleAssignee(ctx, doer, assigneeID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sess.Commit(); err != nil {
|
if err := committer.Commit(); err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return removed, comment, nil
|
return removed, comment, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) toggleAssignee(sess *xorm.Session, doer *User, assigneeID int64, isCreate bool) (removed bool, comment *Comment, err error) {
|
func (issue *Issue) toggleAssignee(ctx context.Context, doer *User, assigneeID int64, isCreate bool) (removed bool, comment *Comment, err error) {
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
removed, err = toggleUserAssignee(sess, issue, assigneeID)
|
removed, err = toggleUserAssignee(sess, issue, assigneeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, fmt.Errorf("UpdateIssueUserByAssignee: %v", err)
|
return false, nil, fmt.Errorf("UpdateIssueUserByAssignee: %v", err)
|
||||||
|
@ -133,7 +132,7 @@ func (issue *Issue) toggleAssignee(sess *xorm.Session, doer *User, assigneeID in
|
||||||
AssigneeID: assigneeID,
|
AssigneeID: assigneeID,
|
||||||
}
|
}
|
||||||
// Comment
|
// Comment
|
||||||
comment, err = createComment(sess, opts)
|
comment, err = createComment(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, fmt.Errorf("createComment: %v", err)
|
return false, nil, fmt.Errorf("createComment: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -147,7 +146,7 @@ func (issue *Issue) toggleAssignee(sess *xorm.Session, doer *User, assigneeID in
|
||||||
}
|
}
|
||||||
|
|
||||||
// toggles user assignee state in database
|
// toggles user assignee state in database
|
||||||
func toggleUserAssignee(e *xorm.Session, issue *Issue, assigneeID int64) (removed bool, err error) {
|
func toggleUserAssignee(e db.Engine, issue *Issue, assigneeID int64) (removed bool, err error) {
|
||||||
// Check if the user exists
|
// Check if the user exists
|
||||||
assignee, err := getUserByID(e, assigneeID)
|
assignee, err := getUserByID(e, assigneeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -15,6 +16,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/issues"
|
"code.gitea.io/gitea/models/issues"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -198,7 +200,7 @@ type Comment struct {
|
||||||
// Reference issue in commit message
|
// Reference issue in commit message
|
||||||
CommitSHA string `xorm:"VARCHAR(40)"`
|
CommitSHA string `xorm:"VARCHAR(40)"`
|
||||||
|
|
||||||
Attachments []*Attachment `xorm:"-"`
|
Attachments []*repo_model.Attachment `xorm:"-"`
|
||||||
Reactions ReactionList `xorm:"-"`
|
Reactions ReactionList `xorm:"-"`
|
||||||
|
|
||||||
// For view issue page.
|
// For view issue page.
|
||||||
|
@ -300,7 +302,7 @@ func (c *Comment) AfterDelete() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := DeleteAttachmentsByComment(c.ID, true)
|
_, err := repo_model.DeleteAttachmentsByComment(c.ID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("Could not delete files for comment %d on issue #%d: %s", c.ID, c.IssueID, err)
|
log.Info("Could not delete files for comment %d on issue #%d: %s", c.ID, c.IssueID, err)
|
||||||
}
|
}
|
||||||
|
@ -483,7 +485,7 @@ func (c *Comment) LoadAttachments() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
c.Attachments, err = getAttachmentsByCommentID(db.GetEngine(db.DefaultContext), c.ID)
|
c.Attachments, err = repo_model.GetAttachmentsByCommentIDCtx(db.DefaultContext, c.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err)
|
log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err)
|
||||||
}
|
}
|
||||||
|
@ -492,23 +494,24 @@ func (c *Comment) LoadAttachments() error {
|
||||||
|
|
||||||
// UpdateAttachments update attachments by UUIDs for the comment
|
// UpdateAttachments update attachments by UUIDs for the comment
|
||||||
func (c *Comment) UpdateAttachments(uuids []string) error {
|
func (c *Comment) UpdateAttachments(uuids []string) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
attachments, err := getAttachmentsByUUIDs(sess, uuids)
|
defer committer.Close()
|
||||||
|
|
||||||
|
attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, uuids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", uuids, err)
|
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", uuids, err)
|
||||||
}
|
}
|
||||||
for i := 0; i < len(attachments); i++ {
|
for i := 0; i < len(attachments); i++ {
|
||||||
attachments[i].IssueID = c.IssueID
|
attachments[i].IssueID = c.IssueID
|
||||||
attachments[i].CommentID = c.ID
|
attachments[i].CommentID = c.ID
|
||||||
if err := updateAttachment(sess, attachments[i]); err != nil {
|
if err := repo_model.UpdateAttachmentCtx(ctx, attachments[i]); err != nil {
|
||||||
return fmt.Errorf("update attachment [id: %d]: %v", attachments[i].ID, err)
|
return fmt.Errorf("update attachment [id: %d]: %v", attachments[i].ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAssigneeUserAndTeam if comment.Type is CommentTypeAssignees, then load assignees
|
// LoadAssigneeUserAndTeam if comment.Type is CommentTypeAssignees, then load assignees
|
||||||
|
@ -715,7 +718,8 @@ func (c *Comment) LoadPushCommits() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func createComment(e db.Engine, opts *CreateCommentOptions) (_ *Comment, err error) {
|
func createComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
var LabelID int64
|
var LabelID int64
|
||||||
if opts.Label != nil {
|
if opts.Label != nil {
|
||||||
LabelID = opts.Label.ID
|
LabelID = opts.Label.ID
|
||||||
|
@ -763,18 +767,19 @@ func createComment(e db.Engine, opts *CreateCommentOptions) (_ *Comment, err err
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = updateCommentInfos(e, opts, comment); err != nil {
|
if err = updateCommentInfos(ctx, opts, comment); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = comment.addCrossReferences(e, opts.Doer, false); err != nil {
|
if err = comment.addCrossReferences(ctx, opts.Doer, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return comment, nil
|
return comment, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateCommentInfos(e db.Engine, opts *CreateCommentOptions, comment *Comment) (err error) {
|
func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment *Comment) (err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
// Check comment type.
|
// Check comment type.
|
||||||
switch opts.Type {
|
switch opts.Type {
|
||||||
case CommentTypeCode:
|
case CommentTypeCode:
|
||||||
|
@ -797,7 +802,7 @@ func updateCommentInfos(e db.Engine, opts *CreateCommentOptions, comment *Commen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check attachments
|
// Check attachments
|
||||||
attachments, err := getAttachmentsByUUIDs(e, opts.Attachments)
|
attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, opts.Attachments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", opts.Attachments, err)
|
return fmt.Errorf("getAttachmentsByUUIDs [uuids: %v]: %v", opts.Attachments, err)
|
||||||
}
|
}
|
||||||
|
@ -819,7 +824,7 @@ func updateCommentInfos(e db.Engine, opts *CreateCommentOptions, comment *Commen
|
||||||
return updateIssueCols(e, opts.Issue, "updated_unix")
|
return updateIssueCols(e, opts.Issue, "updated_unix")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlineUnix timeutil.TimeStamp) (*Comment, error) {
|
func createDeadlineComment(ctx context.Context, doer *User, issue *Issue, newDeadlineUnix timeutil.TimeStamp) (*Comment, error) {
|
||||||
var content string
|
var content string
|
||||||
var commentType CommentType
|
var commentType CommentType
|
||||||
|
|
||||||
|
@ -837,7 +842,7 @@ func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlin
|
||||||
content = newDeadlineUnix.Format("2006-01-02") + "|" + issue.DeadlineUnix.Format("2006-01-02")
|
content = newDeadlineUnix.Format("2006-01-02") + "|" + issue.DeadlineUnix.Format("2006-01-02")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := issue.loadRepo(e); err != nil {
|
if err := issue.loadRepo(db.GetEngine(ctx)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,7 +853,7 @@ func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlin
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Content: content,
|
Content: content,
|
||||||
}
|
}
|
||||||
comment, err := createComment(e, opts)
|
comment, err := createComment(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -856,12 +861,12 @@ func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates issue dependency comment
|
// Creates issue dependency comment
|
||||||
func createIssueDependencyComment(e *xorm.Session, doer *User, issue, dependentIssue *Issue, add bool) (err error) {
|
func createIssueDependencyComment(ctx context.Context, doer *User, issue, dependentIssue *Issue, add bool) (err error) {
|
||||||
cType := CommentTypeAddDependency
|
cType := CommentTypeAddDependency
|
||||||
if !add {
|
if !add {
|
||||||
cType = CommentTypeRemoveDependency
|
cType = CommentTypeRemoveDependency
|
||||||
}
|
}
|
||||||
if err = issue.loadRepo(e); err != nil {
|
if err = issue.loadRepo(db.GetEngine(ctx)); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,7 +878,7 @@ func createIssueDependencyComment(e *xorm.Session, doer *User, issue, dependentI
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
DependentIssueID: dependentIssue.ID,
|
DependentIssueID: dependentIssue.ID,
|
||||||
}
|
}
|
||||||
if _, err = createComment(e, opts); err != nil {
|
if _, err = createComment(ctx, opts); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,7 +889,7 @@ func createIssueDependencyComment(e *xorm.Session, doer *User, issue, dependentI
|
||||||
Issue: dependentIssue,
|
Issue: dependentIssue,
|
||||||
DependentIssueID: issue.ID,
|
DependentIssueID: issue.ID,
|
||||||
}
|
}
|
||||||
_, err = createComment(e, opts)
|
_, err = createComment(ctx, opts)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -928,18 +933,18 @@ type CreateCommentOptions struct {
|
||||||
|
|
||||||
// CreateComment creates comment of issue or commit.
|
// CreateComment creates comment of issue or commit.
|
||||||
func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
|
func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
comment, err = createComment(sess, opts)
|
comment, err = createComment(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
if err = committer.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1068,11 +1073,12 @@ func CountComments(opts *FindCommentsOptions) (int64, error) {
|
||||||
|
|
||||||
// UpdateComment updates information of comment.
|
// UpdateComment updates information of comment.
|
||||||
func UpdateComment(c *Comment, doer *User) error {
|
func UpdateComment(c *Comment, doer *User) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if _, err := sess.ID(c.ID).AllCols().Update(c); err != nil {
|
if _, err := sess.ID(c.ID).AllCols().Update(c); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1080,10 +1086,10 @@ func UpdateComment(c *Comment, doer *User) error {
|
||||||
if err := c.loadIssue(sess); err != nil {
|
if err := c.loadIssue(sess); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := c.addCrossReferences(sess, doer, true); err != nil {
|
if err := c.addCrossReferences(ctx, doer, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := sess.Commit(); err != nil {
|
if err := committer.Commit(); err != nil {
|
||||||
return fmt.Errorf("Commit: %v", err)
|
return fmt.Errorf("Commit: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
|
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import "code.gitea.io/gitea/models/db"
|
import (
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
)
|
||||||
|
|
||||||
// CommentList defines a list of comments
|
// CommentList defines a list of comments
|
||||||
type CommentList []*Comment
|
type CommentList []*Comment
|
||||||
|
@ -393,7 +396,7 @@ func (comments CommentList) loadAttachments(e db.Engine) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments := make(map[int64][]*Attachment, len(comments))
|
attachments := make(map[int64][]*repo_model.Attachment, len(comments))
|
||||||
commentsIDs := comments.getCommentIDs()
|
commentsIDs := comments.getCommentIDs()
|
||||||
left := len(commentsIDs)
|
left := len(commentsIDs)
|
||||||
for left > 0 {
|
for left > 0 {
|
||||||
|
@ -404,13 +407,13 @@ func (comments CommentList) loadAttachments(e db.Engine) (err error) {
|
||||||
rows, err := e.Table("attachment").
|
rows, err := e.Table("attachment").
|
||||||
Join("INNER", "comment", "comment.id = attachment.comment_id").
|
Join("INNER", "comment", "comment.id = attachment.comment_id").
|
||||||
In("comment.id", commentsIDs[:limit]).
|
In("comment.id", commentsIDs[:limit]).
|
||||||
Rows(new(Attachment))
|
Rows(new(repo_model.Attachment))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var attachment Attachment
|
var attachment repo_model.Attachment
|
||||||
err = rows.Scan(&attachment)
|
err = rows.Scan(&attachment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = rows.Close()
|
_ = rows.Close()
|
||||||
|
|
|
@ -37,11 +37,12 @@ const (
|
||||||
|
|
||||||
// CreateIssueDependency creates a new dependency for an issue
|
// CreateIssueDependency creates a new dependency for an issue
|
||||||
func CreateIssueDependency(user *User, issue, dep *Issue) error {
|
func CreateIssueDependency(user *User, issue, dep *Issue) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
// Check if it aleready exists
|
// Check if it aleready exists
|
||||||
exists, err := issueDepExists(sess, issue.ID, dep.ID)
|
exists, err := issueDepExists(sess, issue.ID, dep.ID)
|
||||||
|
@ -69,20 +70,20 @@ func CreateIssueDependency(user *User, issue, dep *Issue) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add comment referencing the new dependency
|
// Add comment referencing the new dependency
|
||||||
if err = createIssueDependencyComment(sess, user, issue, dep, true); err != nil {
|
if err = createIssueDependencyComment(ctx, user, issue, dep, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveIssueDependency removes a dependency from an issue
|
// RemoveIssueDependency removes a dependency from an issue
|
||||||
func RemoveIssueDependency(user *User, issue, dep *Issue, depType DependencyType) (err error) {
|
func RemoveIssueDependency(user *User, issue, dep *Issue, depType DependencyType) (err error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
var issueDepToDelete IssueDependency
|
var issueDepToDelete IssueDependency
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ func RemoveIssueDependency(user *User, issue, dep *Issue, depType DependencyType
|
||||||
return ErrUnknownDependencyType{depType}
|
return ErrUnknownDependencyType{depType}
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := sess.Delete(&issueDepToDelete)
|
affected, err := db.GetEngine(ctx).Delete(&issueDepToDelete)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -106,10 +107,10 @@ func RemoveIssueDependency(user *User, issue, dep *Issue, depType DependencyType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add comment referencing the removed dependency
|
// Add comment referencing the removed dependency
|
||||||
if err = createIssueDependencyComment(sess, user, issue, dep, false); err != nil {
|
if err = createIssueDependencyComment(ctx, user, issue, dep, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the dependency already exists
|
// Check if the dependency already exists
|
||||||
|
|
|
@ -663,7 +663,8 @@ func HasIssueLabel(issueID, labelID int64) bool {
|
||||||
|
|
||||||
// newIssueLabel this function creates a new label it does not check if the label is valid for the issue
|
// newIssueLabel this function creates a new label it does not check if the label is valid for the issue
|
||||||
// YOU MUST CHECK THIS BEFORE THIS FUNCTION
|
// YOU MUST CHECK THIS BEFORE THIS FUNCTION
|
||||||
func newIssueLabel(e db.Engine, issue *Issue, label *Label, doer *User) (err error) {
|
func newIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *User) (err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
if _, err = e.Insert(&IssueLabel{
|
if _, err = e.Insert(&IssueLabel{
|
||||||
IssueID: issue.ID,
|
IssueID: issue.ID,
|
||||||
LabelID: label.ID,
|
LabelID: label.ID,
|
||||||
|
@ -683,7 +684,7 @@ func newIssueLabel(e db.Engine, issue *Issue, label *Label, doer *User) (err err
|
||||||
Label: label,
|
Label: label,
|
||||||
Content: "1",
|
Content: "1",
|
||||||
}
|
}
|
||||||
if _, err = createComment(e, opts); err != nil {
|
if _, err = createComment(ctx, opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,11 +697,12 @@ func NewIssueLabel(issue *Issue, label *Label, doer *User) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if err = issue.loadRepo(sess); err != nil {
|
if err = issue.loadRepo(sess); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -711,7 +713,7 @@ func NewIssueLabel(issue *Issue, label *Label, doer *User) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = newIssueLabel(sess, issue, label, doer); err != nil {
|
if err = newIssueLabel(ctx, issue, label, doer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,11 +722,12 @@ func NewIssueLabel(issue *Issue, label *Label, doer *User) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// newIssueLabels add labels to an issue. It will check if the labels are valid for the issue
|
// newIssueLabels add labels to an issue. It will check if the labels are valid for the issue
|
||||||
func newIssueLabels(e db.Engine, issue *Issue, labels []*Label, doer *User) (err error) {
|
func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *User) (err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
if err = issue.loadRepo(e); err != nil {
|
if err = issue.loadRepo(e); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -735,7 +738,7 @@ func newIssueLabels(e db.Engine, issue *Issue, labels []*Label, doer *User) (err
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = newIssueLabel(e, issue, label, doer); err != nil {
|
if err = newIssueLabel(ctx, issue, label, doer); err != nil {
|
||||||
return fmt.Errorf("newIssueLabel: %v", err)
|
return fmt.Errorf("newIssueLabel: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,7 +754,7 @@ func NewIssueLabels(issue *Issue, labels []*Label, doer *User) (err error) {
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
if err = newIssueLabels(db.GetEngine(ctx), issue, labels, doer); err != nil {
|
if err = newIssueLabels(ctx, issue, labels, doer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,7 +766,8 @@ func NewIssueLabels(issue *Issue, labels []*Label, doer *User) (err error) {
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteIssueLabel(e db.Engine, issue *Issue, label *Label, doer *User) (err error) {
|
func deleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *User) (err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
if count, err := e.Delete(&IssueLabel{
|
if count, err := e.Delete(&IssueLabel{
|
||||||
IssueID: issue.ID,
|
IssueID: issue.ID,
|
||||||
LabelID: label.ID,
|
LabelID: label.ID,
|
||||||
|
@ -784,7 +788,7 @@ func deleteIssueLabel(e db.Engine, issue *Issue, label *Label, doer *User) (err
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Label: label,
|
Label: label,
|
||||||
}
|
}
|
||||||
if _, err = createComment(e, opts); err != nil {
|
if _, err = createComment(ctx, opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,22 +797,22 @@ func deleteIssueLabel(e db.Engine, issue *Issue, label *Label, doer *User) (err
|
||||||
|
|
||||||
// DeleteIssueLabel deletes issue-label relation.
|
// DeleteIssueLabel deletes issue-label relation.
|
||||||
func DeleteIssueLabel(issue *Issue, label *Label, doer *User) (err error) {
|
func DeleteIssueLabel(issue *Issue, label *Label, doer *User) (err error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
if err = deleteIssueLabel(sess, issue, label, doer); err != nil {
|
if err = deleteIssueLabel(ctx, issue, label, doer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
issue.Labels = nil
|
issue.Labels = nil
|
||||||
if err = issue.loadLabels(sess); err != nil {
|
if err = issue.loadLabels(db.GetEngine(ctx)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteLabelsByRepoID(sess db.Engine, repoID int64) error {
|
func deleteLabelsByRepoID(sess db.Engine, repoID int64) error {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
@ -322,7 +323,7 @@ func (issues IssueList) loadAttachments(e db.Engine) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments := make(map[int64][]*Attachment, len(issues))
|
attachments := make(map[int64][]*repo_model.Attachment, len(issues))
|
||||||
issuesIDs := issues.getIssueIDs()
|
issuesIDs := issues.getIssueIDs()
|
||||||
left := len(issuesIDs)
|
left := len(issuesIDs)
|
||||||
for left > 0 {
|
for left > 0 {
|
||||||
|
@ -333,13 +334,13 @@ func (issues IssueList) loadAttachments(e db.Engine) (err error) {
|
||||||
rows, err := e.Table("attachment").
|
rows, err := e.Table("attachment").
|
||||||
Join("INNER", "issue", "issue.id = attachment.issue_id").
|
Join("INNER", "issue", "issue.id = attachment.issue_id").
|
||||||
In("issue.id", issuesIDs[:limit]).
|
In("issue.id", issuesIDs[:limit]).
|
||||||
Rows(new(Attachment))
|
Rows(new(repo_model.Attachment))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var attachment Attachment
|
var attachment repo_model.Attachment
|
||||||
err = rows.Scan(&attachment)
|
err = rows.Scan(&attachment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err1 := rows.Close(); err1 != nil {
|
if err1 := rows.Close(); err1 != nil {
|
||||||
|
|
|
@ -37,13 +37,13 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error {
|
||||||
commentType = CommentTypeUnlock
|
commentType = CommentTypeUnlock
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
if err := updateIssueCols(sess, opts.Issue, "is_locked"); err != nil {
|
if err := updateIssueCols(db.GetEngine(ctx), opts.Issue, "is_locked"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +54,9 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error {
|
||||||
Type: commentType,
|
Type: commentType,
|
||||||
Content: opts.Reason,
|
Content: opts.Reason,
|
||||||
}
|
}
|
||||||
if _, err := createComment(sess, opt); err != nil {
|
if _, err := createComment(ctx, opt); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -15,7 +16,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
"xorm.io/xorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Milestone represents a milestone of repository.
|
// Milestone represents a milestone of repository.
|
||||||
|
@ -263,7 +263,8 @@ func changeMilestoneStatus(e db.Engine, m *Milestone, isClosed bool) error {
|
||||||
return updateRepoMilestoneNum(e, m.RepoID)
|
return updateRepoMilestoneNum(e, m.RepoID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func changeMilestoneAssign(e *xorm.Session, doer *User, issue *Issue, oldMilestoneID int64) error {
|
func changeMilestoneAssign(ctx context.Context, doer *User, issue *Issue, oldMilestoneID int64) error {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
if err := updateIssueCols(e, issue, "milestone_id"); err != nil {
|
if err := updateIssueCols(e, issue, "milestone_id"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -293,7 +294,7 @@ func changeMilestoneAssign(e *xorm.Session, doer *User, issue *Issue, oldMilesto
|
||||||
OldMilestoneID: oldMilestoneID,
|
OldMilestoneID: oldMilestoneID,
|
||||||
MilestoneID: issue.MilestoneID,
|
MilestoneID: issue.MilestoneID,
|
||||||
}
|
}
|
||||||
if _, err := createComment(e, opts); err != nil {
|
if _, err := createComment(ctx, opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,17 +304,17 @@ func changeMilestoneAssign(e *xorm.Session, doer *User, issue *Issue, oldMilesto
|
||||||
|
|
||||||
// ChangeMilestoneAssign changes assignment of milestone for issue.
|
// ChangeMilestoneAssign changes assignment of milestone for issue.
|
||||||
func ChangeMilestoneAssign(issue *Issue, doer *User, oldMilestoneID int64) (err error) {
|
func ChangeMilestoneAssign(issue *Issue, doer *User, oldMilestoneID int64) (err error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
if err = changeMilestoneAssign(ctx, doer, issue, oldMilestoneID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = changeMilestoneAssign(sess, doer, issue, oldMilestoneID); err != nil {
|
if err = committer.Commit(); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
|
||||||
return fmt.Errorf("Commit: %v", err)
|
return fmt.Errorf("Commit: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -5,13 +5,12 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stopwatch represents a stopwatch for time tracking.
|
// Stopwatch represents a stopwatch for time tracking.
|
||||||
|
@ -86,18 +85,19 @@ func hasUserStopwatch(e db.Engine, userID int64) (exists bool, sw *Stopwatch, er
|
||||||
|
|
||||||
// CreateOrStopIssueStopwatch will create or remove a stopwatch and will log it into issue's timeline.
|
// CreateOrStopIssueStopwatch will create or remove a stopwatch and will log it into issue's timeline.
|
||||||
func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := createOrStopIssueStopwatch(sess, user, issue); err != nil {
|
defer committer.Close()
|
||||||
|
if err := createOrStopIssueStopwatch(ctx, user, issue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createOrStopIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
func createOrStopIssueStopwatch(ctx context.Context, user *User, issue *Issue) error {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
sw, exists, err := getStopwatch(e, user.ID, issue.ID)
|
sw, exists, err := getStopwatch(e, user.ID, issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -122,7 +122,7 @@ func createOrStopIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := createComment(e, &CreateCommentOptions{
|
if _, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Doer: user,
|
Doer: user,
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
@ -146,7 +146,7 @@ func createOrStopIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := createOrStopIssueStopwatch(e, user, issue); err != nil {
|
if err := createOrStopIssueStopwatch(ctx, user, issue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,11 +157,11 @@ func createOrStopIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error
|
||||||
IssueID: issue.ID,
|
IssueID: issue.ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := e.Insert(sw); err != nil {
|
if err := db.Insert(ctx, sw); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := createComment(e, &CreateCommentOptions{
|
if _, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Doer: user,
|
Doer: user,
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
@ -175,18 +175,19 @@ func createOrStopIssueStopwatch(e *xorm.Session, user *User, issue *Issue) error
|
||||||
|
|
||||||
// CancelStopwatch removes the given stopwatch and logs it into issue's timeline.
|
// CancelStopwatch removes the given stopwatch and logs it into issue's timeline.
|
||||||
func CancelStopwatch(user *User, issue *Issue) error {
|
func CancelStopwatch(user *User, issue *Issue) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := cancelStopwatch(sess, user, issue); err != nil {
|
defer committer.Close()
|
||||||
|
if err := cancelStopwatch(ctx, user, issue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func cancelStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
func cancelStopwatch(ctx context.Context, user *User, issue *Issue) error {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
sw, exists, err := getStopwatch(e, user.ID, issue.ID)
|
sw, exists, err := getStopwatch(e, user.ID, issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -201,7 +202,7 @@ func cancelStopwatch(e *xorm.Session, user *User, issue *Issue) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := createComment(e, &CreateCommentOptions{
|
if _, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Doer: user,
|
Doer: user,
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
|
|
@ -154,12 +154,12 @@ func GetTrackedSeconds(opts FindTrackedTimesOptions) (int64, error) {
|
||||||
|
|
||||||
// AddTime will add the given time (in seconds) to the issue
|
// AddTime will add the given time (in seconds) to the issue
|
||||||
func AddTime(user *User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
func AddTime(user *User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
|
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
t, err := addTime(sess, user, issue, amount, created)
|
t, err := addTime(sess, user, issue, amount, created)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,7 +170,7 @@ func AddTime(user *User, issue *Issue, amount int64, created time.Time) (*Tracke
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := createComment(sess, &CreateCommentOptions{
|
if _, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
Doer: user,
|
Doer: user,
|
||||||
|
@ -181,7 +181,7 @@ func AddTime(user *User, issue *Issue, amount int64, created time.Time) (*Tracke
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return t, sess.Commit()
|
return t, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func addTime(e db.Engine, user *User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
func addTime(e db.Engine, user *User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
||||||
|
@ -230,12 +230,12 @@ func TotalTimes(options *FindTrackedTimesOptions) (map[*User]string, error) {
|
||||||
|
|
||||||
// DeleteIssueUserTimes deletes times for issue
|
// DeleteIssueUserTimes deletes times for issue
|
||||||
func DeleteIssueUserTimes(issue *Issue, user *User) error {
|
func DeleteIssueUserTimes(issue *Issue, user *User) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
|
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
opts := FindTrackedTimesOptions{
|
opts := FindTrackedTimesOptions{
|
||||||
IssueID: issue.ID,
|
IssueID: issue.ID,
|
||||||
|
@ -253,7 +253,7 @@ func DeleteIssueUserTimes(issue *Issue, user *User) error {
|
||||||
if err := issue.loadRepo(sess); err != nil {
|
if err := issue.loadRepo(sess); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := createComment(sess, &CreateCommentOptions{
|
if _, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
Doer: user,
|
Doer: user,
|
||||||
|
@ -263,17 +263,17 @@ func DeleteIssueUserTimes(issue *Issue, user *User) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteTime delete a specific Time
|
// DeleteTime delete a specific Time
|
||||||
func DeleteTime(t *TrackedTime) error {
|
func DeleteTime(t *TrackedTime) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
|
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if err := t.loadAttributes(sess); err != nil {
|
if err := t.loadAttributes(sess); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -283,7 +283,7 @@ func DeleteTime(t *TrackedTime) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := createComment(sess, &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,
|
||||||
|
@ -293,7 +293,7 @@ func DeleteTime(t *TrackedTime) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteTimes(e db.Engine, opts FindTrackedTimesOptions) (removedTime int64, err error) {
|
func deleteTimes(e db.Engine, opts FindTrackedTimesOptions) (removedTime int64, err error) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
@ -59,7 +60,7 @@ func neuterCrossReferencesIds(e db.Engine, ids []int64) error {
|
||||||
// \/ \/ \/
|
// \/ \/ \/
|
||||||
//
|
//
|
||||||
|
|
||||||
func (issue *Issue) addCrossReferences(e db.Engine, doer *User, removeOld bool) error {
|
func (issue *Issue) addCrossReferences(stdCtx context.Context, doer *User, removeOld bool) error {
|
||||||
var commentType CommentType
|
var commentType CommentType
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
commentType = CommentTypePullRef
|
commentType = CommentTypePullRef
|
||||||
|
@ -72,10 +73,11 @@ func (issue *Issue) addCrossReferences(e db.Engine, doer *User, removeOld bool)
|
||||||
OrigIssue: issue,
|
OrigIssue: issue,
|
||||||
RemoveOld: removeOld,
|
RemoveOld: removeOld,
|
||||||
}
|
}
|
||||||
return issue.createCrossReferences(e, ctx, issue.Title, issue.Content)
|
return issue.createCrossReferences(stdCtx, ctx, issue.Title, issue.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) createCrossReferences(e db.Engine, ctx *crossReferencesContext, plaincontent, mdcontent string) error {
|
func (issue *Issue) createCrossReferences(stdCtx context.Context, ctx *crossReferencesContext, plaincontent, mdcontent string) error {
|
||||||
|
e := db.GetEngine(stdCtx)
|
||||||
xreflist, err := ctx.OrigIssue.getCrossReferences(e, ctx, plaincontent, mdcontent)
|
xreflist, err := ctx.OrigIssue.getCrossReferences(e, ctx, plaincontent, mdcontent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -125,7 +127,7 @@ func (issue *Issue) createCrossReferences(e db.Engine, ctx *crossReferencesConte
|
||||||
RefAction: xref.Action,
|
RefAction: xref.Action,
|
||||||
RefIsPull: ctx.OrigIssue.IsPull,
|
RefIsPull: ctx.OrigIssue.IsPull,
|
||||||
}
|
}
|
||||||
_, err := createComment(e, opts)
|
_, err := createComment(stdCtx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -240,11 +242,11 @@ func (issue *Issue) verifyReferencedIssue(e db.Engine, ctx *crossReferencesConte
|
||||||
// \/ \/ \/ \/ \/
|
// \/ \/ \/ \/ \/
|
||||||
//
|
//
|
||||||
|
|
||||||
func (comment *Comment) addCrossReferences(e db.Engine, doer *User, removeOld bool) error {
|
func (comment *Comment) addCrossReferences(stdCtx context.Context, doer *User, removeOld bool) error {
|
||||||
if comment.Type != CommentTypeCode && comment.Type != CommentTypeComment {
|
if comment.Type != CommentTypeCode && comment.Type != CommentTypeComment {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := comment.loadIssue(e); err != nil {
|
if err := comment.loadIssue(db.GetEngine(stdCtx)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ctx := &crossReferencesContext{
|
ctx := &crossReferencesContext{
|
||||||
|
@ -254,7 +256,7 @@ func (comment *Comment) addCrossReferences(e db.Engine, doer *User, removeOld bo
|
||||||
OrigComment: comment,
|
OrigComment: comment,
|
||||||
RemoveOld: removeOld,
|
RemoveOld: removeOld,
|
||||||
}
|
}
|
||||||
return comment.Issue.createCrossReferences(e, ctx, "", comment.Content)
|
return comment.Issue.createCrossReferences(stdCtx, ctx, "", comment.Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (comment *Comment) neuterCrossReferences(e db.Engine) error {
|
func (comment *Comment) neuterCrossReferences(e db.Engine) error {
|
||||||
|
|
|
@ -140,19 +140,18 @@ func testCreateIssue(t *testing.T, repo, doer int64, title, content string, ispu
|
||||||
Index: idx,
|
Index: idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
assert.NoError(t, err)
|
||||||
|
defer committer.Close()
|
||||||
assert.NoError(t, sess.Begin())
|
err = newIssue(ctx, d, NewIssueOptions{
|
||||||
err = newIssue(sess, d, NewIssueOptions{
|
|
||||||
Repo: r,
|
Repo: r,
|
||||||
Issue: i,
|
Issue: i,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
i, err = getIssueByID(sess, i.ID)
|
i, err = getIssueByID(db.GetEngine(ctx), i.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, i.addCrossReferences(sess, d, false))
|
assert.NoError(t, i.addCrossReferences(ctx, d, false))
|
||||||
assert.NoError(t, sess.Commit())
|
assert.NoError(t, committer.Commit())
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +170,12 @@ func testCreateComment(t *testing.T, repo, doer, issue int64, content string) *C
|
||||||
i := unittest.AssertExistsAndLoadBean(t, &Issue{ID: issue}).(*Issue)
|
i := unittest.AssertExistsAndLoadBean(t, &Issue{ID: issue}).(*Issue)
|
||||||
c := &Comment{Type: CommentTypeComment, PosterID: doer, Poster: d, IssueID: issue, Issue: i, Content: content}
|
c := &Comment{Type: CommentTypeComment, PosterID: doer, Poster: d, IssueID: issue, Issue: i, Content: content}
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
|
||||||
assert.NoError(t, sess.Begin())
|
|
||||||
_, err := sess.Insert(c)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, c.addCrossReferences(sess, d, false))
|
defer committer.Close()
|
||||||
assert.NoError(t, sess.Commit())
|
err = db.Insert(ctx, c)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, c.addCrossReferences(ctx, d, false))
|
||||||
|
assert.NoError(t, committer.Commit())
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -391,14 +392,15 @@ func countUnread(e db.Engine, userID int64) int64 {
|
||||||
|
|
||||||
// LoadAttributes load Repo Issue User and Comment if not loaded
|
// LoadAttributes load Repo Issue User and Comment if not loaded
|
||||||
func (n *Notification) LoadAttributes() (err error) {
|
func (n *Notification) LoadAttributes() (err error) {
|
||||||
return n.loadAttributes(db.GetEngine(db.DefaultContext))
|
return n.loadAttributes(db.DefaultContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) loadAttributes(e db.Engine) (err error) {
|
func (n *Notification) loadAttributes(ctx context.Context) (err error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
if err = n.loadRepo(e); err != nil {
|
if err = n.loadRepo(e); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = n.loadIssue(e); err != nil {
|
if err = n.loadIssue(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = n.loadUser(e); err != nil {
|
if err = n.loadUser(e); err != nil {
|
||||||
|
@ -420,13 +422,13 @@ func (n *Notification) loadRepo(e db.Engine) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) loadIssue(e db.Engine) (err error) {
|
func (n *Notification) loadIssue(ctx context.Context) (err error) {
|
||||||
if n.Issue == nil && n.IssueID != 0 {
|
if n.Issue == nil && n.IssueID != 0 {
|
||||||
n.Issue, err = getIssueByID(e, n.IssueID)
|
n.Issue, err = getIssueByID(db.GetEngine(ctx), n.IssueID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getIssueByID [%d]: %v", n.IssueID, err)
|
return fmt.Errorf("getIssueByID [%d]: %v", n.IssueID, err)
|
||||||
}
|
}
|
||||||
return n.Issue.loadAttributes(e)
|
return n.Issue.loadAttributes(ctx)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -464,7 +466,7 @@ func (n *Notification) GetRepo() (*Repository, error) {
|
||||||
|
|
||||||
// GetIssue returns the issue of the notification
|
// GetIssue returns the issue of the notification
|
||||||
func (n *Notification) GetIssue() (*Issue, error) {
|
func (n *Notification) GetIssue() (*Issue, error) {
|
||||||
return n.Issue, n.loadIssue(db.GetEngine(db.DefaultContext))
|
return n.Issue, n.loadIssue(db.DefaultContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTMLURL formats a URL-string to the notification
|
// HTMLURL formats a URL-string to the notification
|
||||||
|
|
|
@ -5,11 +5,10 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProjectIssue saves relation from issue to a project
|
// ProjectIssue saves relation from issue to a project
|
||||||
|
@ -132,20 +131,21 @@ func (p *Project) NumOpenIssues() int {
|
||||||
|
|
||||||
// ChangeProjectAssign changes the project associated with an issue
|
// ChangeProjectAssign changes the project associated with an issue
|
||||||
func ChangeProjectAssign(issue *Issue, doer *User, newProjectID int64) error {
|
func ChangeProjectAssign(issue *Issue, doer *User, newProjectID int64) error {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
return err
|
||||||
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
|
if err := addUpdateIssueProject(ctx, issue, doer, newProjectID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := addUpdateIssueProject(sess, issue, doer, newProjectID); err != nil {
|
return committer.Commit()
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *User, newProjectID int64) error {
|
||||||
}
|
e := db.GetEngine(ctx)
|
||||||
|
|
||||||
func addUpdateIssueProject(e *xorm.Session, issue *Issue, doer *User, newProjectID int64) error {
|
|
||||||
oldProjectID := issue.projectID(e)
|
oldProjectID := issue.projectID(e)
|
||||||
|
|
||||||
if _, err := e.Where("project_issue.issue_id=?", issue.ID).Delete(&ProjectIssue{}); err != nil {
|
if _, err := e.Where("project_issue.issue_id=?", issue.ID).Delete(&ProjectIssue{}); err != nil {
|
||||||
|
@ -157,7 +157,7 @@ func addUpdateIssueProject(e *xorm.Session, issue *Issue, doer *User, newProject
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldProjectID > 0 || newProjectID > 0 {
|
if oldProjectID > 0 || newProjectID > 0 {
|
||||||
if _, err := createComment(e, &CreateCommentOptions{
|
if _, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Type: CommentTypeProject,
|
Type: CommentTypeProject,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
|
|
@ -394,11 +394,12 @@ func (pr *PullRequest) SetMerged() (bool, error) {
|
||||||
|
|
||||||
pr.HasMerged = true
|
pr.HasMerged = true
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
if _, err := sess.Exec("UPDATE `issue` SET `repo_id` = `repo_id` WHERE `id` = ?", pr.IssueID); err != nil {
|
if _, err := sess.Exec("UPDATE `issue` SET `repo_id` = `repo_id` WHERE `id` = ?", pr.IssueID); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -432,7 +433,7 @@ func (pr *PullRequest) SetMerged() (bool, error) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := pr.Issue.changeStatus(sess, pr.Merger, true, true); err != nil {
|
if _, err := pr.Issue.changeStatus(ctx, pr.Merger, true, true); err != nil {
|
||||||
return false, fmt.Errorf("Issue.changeStatus: %v", err)
|
return false, fmt.Errorf("Issue.changeStatus: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +442,7 @@ func (pr *PullRequest) SetMerged() (bool, error) {
|
||||||
return false, fmt.Errorf("Failed to update pr[%d]: %v", pr.ID, err)
|
return false, fmt.Errorf("Failed to update pr[%d]: %v", pr.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sess.Commit(); err != nil {
|
if err := committer.Commit(); err != nil {
|
||||||
return false, fmt.Errorf("Commit: %v", err)
|
return false, fmt.Errorf("Commit: %v", err)
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
|
@ -456,13 +457,13 @@ func NewPullRequest(repo *Repository, issue *Issue, labelIDs []int64, uuids []st
|
||||||
|
|
||||||
issue.Index = idx
|
issue.Index = idx
|
||||||
|
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err = sess.Begin(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
|
||||||
if err = newIssue(sess, issue.Poster, NewIssueOptions{
|
if err = newIssue(ctx, issue.Poster, NewIssueOptions{
|
||||||
Repo: repo,
|
Repo: repo,
|
||||||
Issue: issue,
|
Issue: issue,
|
||||||
LabelIDs: labelIDs,
|
LabelIDs: labelIDs,
|
||||||
|
@ -478,11 +479,11 @@ func NewPullRequest(repo *Repository, issue *Issue, labelIDs []int64, uuids []st
|
||||||
pr.Index = issue.Index
|
pr.Index = issue.Index
|
||||||
pr.BaseRepo = repo
|
pr.BaseRepo = repo
|
||||||
pr.IssueID = issue.ID
|
pr.IssueID = issue.ID
|
||||||
if _, err = sess.Insert(pr); err != nil {
|
if err = db.Insert(ctx, pr); err != nil {
|
||||||
return fmt.Errorf("insert pull repo: %v", err)
|
return fmt.Errorf("insert pull repo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
if err = committer.Commit(); err != nil {
|
||||||
return fmt.Errorf("Commit: %v", err)
|
return fmt.Errorf("Commit: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
@ -42,7 +43,7 @@ type Release struct {
|
||||||
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
|
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
|
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
Attachments []*Attachment `xorm:"-"`
|
Attachments []*repo_model.Attachment `xorm:"-"`
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX"`
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +127,7 @@ func UpdateRelease(ctx context.Context, rel *Release) error {
|
||||||
// AddReleaseAttachments adds a release attachments
|
// AddReleaseAttachments adds a release attachments
|
||||||
func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs []string) (err error) {
|
func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs []string) (err error) {
|
||||||
// Check attachments
|
// Check attachments
|
||||||
attachments, err := getAttachmentsByUUIDs(db.GetEngine(ctx), attachmentUUIDs)
|
attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, attachmentUUIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %v", attachmentUUIDs, err)
|
return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %v", attachmentUUIDs, err)
|
||||||
}
|
}
|
||||||
|
@ -295,9 +296,9 @@ func getReleaseAttachments(e db.Engine, rels ...*Release) (err error) {
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
sortedRels := releaseMetaSearch{ID: make([]int64, len(rels)), Rel: make([]*Release, len(rels))}
|
sortedRels := releaseMetaSearch{ID: make([]int64, len(rels)), Rel: make([]*Release, len(rels))}
|
||||||
var attachments []*Attachment
|
var attachments []*repo_model.Attachment
|
||||||
for index, element := range rels {
|
for index, element := range rels {
|
||||||
element.Attachments = []*Attachment{}
|
element.Attachments = []*repo_model.Attachment{}
|
||||||
sortedRels.ID[index] = element.ID
|
sortedRels.ID[index] = element.ID
|
||||||
sortedRels.Rel[index] = element
|
sortedRels.Rel[index] = element
|
||||||
}
|
}
|
||||||
|
@ -307,7 +308,7 @@ func getReleaseAttachments(e db.Engine, rels ...*Release) (err error) {
|
||||||
err = e.
|
err = e.
|
||||||
Asc("release_id", "name").
|
Asc("release_id", "name").
|
||||||
In("release_id", sortedRels.ID).
|
In("release_id", sortedRels.ID).
|
||||||
Find(&attachments, Attachment{})
|
Find(&attachments, repo_model.Attachment{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
|
|
||||||
admin_model "code.gitea.io/gitea/models/admin"
|
admin_model "code.gitea.io/gitea/models/admin"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/models/webhook"
|
"code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/modules/lfs"
|
"code.gitea.io/gitea/modules/lfs"
|
||||||
|
@ -1485,7 +1486,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attachments := make([]*Attachment, 0, 20)
|
attachments := make([]*repo_model.Attachment, 0, 20)
|
||||||
if err = sess.Join("INNER", "`release`", "`release`.id = `attachment`.release_id").
|
if err = sess.Join("INNER", "`release`", "`release`.id = `attachment`.release_id").
|
||||||
Where("`release`.repo_id = ?", repoID).
|
Where("`release`.repo_id = ?", repoID).
|
||||||
Find(&attachments); err != nil {
|
Find(&attachments); err != nil {
|
||||||
|
@ -1620,7 +1621,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all attachments with both issue_id and release_id are zero
|
// Get all attachments with both issue_id and release_id are zero
|
||||||
var newAttachments []*Attachment
|
var newAttachments []*repo_model.Attachment
|
||||||
if err := sess.Where(builder.Eq{
|
if err := sess.Where(builder.Eq{
|
||||||
"repo_id": repo.ID,
|
"repo_id": repo.ID,
|
||||||
"issue_id": 0,
|
"issue_id": 0,
|
||||||
|
@ -1634,7 +1635,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||||
newAttachmentPaths = append(newAttachmentPaths, attach.RelativePath())
|
newAttachmentPaths = append(newAttachmentPaths, attach.RelativePath())
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := sess.Where("repo_id=?", repo.ID).Delete(new(Attachment)); err != nil {
|
if _, err := sess.Where("repo_id=?", repo.ID).Delete(new(repo_model.Attachment)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2191,3 +2192,27 @@ func IterateRepository(f func(repo *Repository) error) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LinkedRepository returns the linked repo if any
|
||||||
|
func LinkedRepository(a *repo_model.Attachment) (*Repository, unit.Type, error) {
|
||||||
|
if a.IssueID != 0 {
|
||||||
|
iss, err := GetIssueByID(a.IssueID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, unit.TypeIssues, err
|
||||||
|
}
|
||||||
|
repo, err := GetRepositoryByID(iss.RepoID)
|
||||||
|
unitType := unit.TypeIssues
|
||||||
|
if iss.IsPull {
|
||||||
|
unitType = unit.TypePullRequests
|
||||||
|
}
|
||||||
|
return repo, unitType, err
|
||||||
|
} else if a.ReleaseID != 0 {
|
||||||
|
rel, err := GetReleaseByID(a.ReleaseID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, unit.TypeReleases, err
|
||||||
|
}
|
||||||
|
repo, err := GetRepositoryByID(rel.RepoID)
|
||||||
|
return repo, unit.TypeReleases, err
|
||||||
|
}
|
||||||
|
return nil, -1, nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -11,12 +11,9 @@ import (
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unit"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attachment represent a attachment of issue/comment/release.
|
// Attachment represent a attachment of issue/comment/release.
|
||||||
|
@ -63,35 +60,34 @@ func (a *Attachment) DownloadURL() string {
|
||||||
return setting.AppURL + "attachments/" + url.PathEscape(a.UUID)
|
return setting.AppURL + "attachments/" + url.PathEscape(a.UUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinkedRepository returns the linked repo if any
|
|
||||||
func (a *Attachment) LinkedRepository() (*Repository, unit.Type, error) {
|
|
||||||
if a.IssueID != 0 {
|
|
||||||
iss, err := GetIssueByID(a.IssueID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, unit.TypeIssues, err
|
|
||||||
}
|
|
||||||
repo, err := GetRepositoryByID(iss.RepoID)
|
|
||||||
unitType := unit.TypeIssues
|
|
||||||
if iss.IsPull {
|
|
||||||
unitType = unit.TypePullRequests
|
|
||||||
}
|
|
||||||
return repo, unitType, err
|
|
||||||
} else if a.ReleaseID != 0 {
|
|
||||||
rel, err := GetReleaseByID(a.ReleaseID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, unit.TypeReleases, err
|
|
||||||
}
|
|
||||||
repo, err := GetRepositoryByID(rel.RepoID)
|
|
||||||
return repo, unit.TypeReleases, err
|
|
||||||
}
|
|
||||||
return nil, -1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAttachmentByID returns attachment by given id
|
// GetAttachmentByID returns attachment by given id
|
||||||
func GetAttachmentByID(id int64) (*Attachment, error) {
|
func GetAttachmentByID(id int64) (*Attachment, error) {
|
||||||
return getAttachmentByID(db.GetEngine(db.DefaultContext), id)
|
return getAttachmentByID(db.GetEngine(db.DefaultContext), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// _____ __ __ .__ __
|
||||||
|
// / _ \_/ |__/ |______ ____ | |__ _____ ____ _____/ |_
|
||||||
|
// / /_\ \ __\ __\__ \ _/ ___\| | \ / \_/ __ \ / \ __\
|
||||||
|
// / | \ | | | / __ \\ \___| Y \ Y Y \ ___/| | \ |
|
||||||
|
// \____|__ /__| |__| (____ /\___ >___| /__|_| /\___ >___| /__|
|
||||||
|
// \/ \/ \/ \/ \/ \/ \/
|
||||||
|
|
||||||
|
// ErrAttachmentNotExist represents a "AttachmentNotExist" kind of error.
|
||||||
|
type ErrAttachmentNotExist struct {
|
||||||
|
ID int64
|
||||||
|
UUID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrAttachmentNotExist checks if an error is a ErrAttachmentNotExist.
|
||||||
|
func IsErrAttachmentNotExist(err error) bool {
|
||||||
|
_, ok := err.(ErrAttachmentNotExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrAttachmentNotExist) Error() string {
|
||||||
|
return fmt.Sprintf("attachment does not exist [id: %d, uuid: %s]", err.ID, err.UUID)
|
||||||
|
}
|
||||||
|
|
||||||
func getAttachmentByID(e db.Engine, id int64) (*Attachment, error) {
|
func getAttachmentByID(e db.Engine, id int64) (*Attachment, error) {
|
||||||
attach := &Attachment{}
|
attach := &Attachment{}
|
||||||
if has, err := e.ID(id).Get(attach); err != nil {
|
if has, err := e.ID(id).Get(attach); err != nil {
|
||||||
|
@ -143,24 +139,26 @@ func GetAttachmentByReleaseIDFileName(releaseID int64, fileName string) (*Attach
|
||||||
return getAttachmentByReleaseIDFileName(db.GetEngine(db.DefaultContext), releaseID, fileName)
|
return getAttachmentByReleaseIDFileName(db.GetEngine(db.DefaultContext), releaseID, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAttachmentsByIssueID(e db.Engine, issueID int64) ([]*Attachment, error) {
|
// GetAttachmentsByIssueIDCtx returns all attachments of an issue.
|
||||||
|
func GetAttachmentsByIssueIDCtx(ctx context.Context, issueID int64) ([]*Attachment, error) {
|
||||||
attachments := make([]*Attachment, 0, 10)
|
attachments := make([]*Attachment, 0, 10)
|
||||||
return attachments, e.Where("issue_id = ? AND comment_id = 0", issueID).Find(&attachments)
|
return attachments, db.GetEngine(ctx).Where("issue_id = ? AND comment_id = 0", issueID).Find(&attachments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAttachmentsByIssueID returns all attachments of an issue.
|
// GetAttachmentsByIssueID returns all attachments of an issue.
|
||||||
func GetAttachmentsByIssueID(issueID int64) ([]*Attachment, error) {
|
func GetAttachmentsByIssueID(issueID int64) ([]*Attachment, error) {
|
||||||
return getAttachmentsByIssueID(db.GetEngine(db.DefaultContext), issueID)
|
return GetAttachmentsByIssueIDCtx(db.DefaultContext, issueID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAttachmentsByCommentID returns all attachments if comment by given ID.
|
// GetAttachmentsByCommentID returns all attachments if comment by given ID.
|
||||||
func GetAttachmentsByCommentID(commentID int64) ([]*Attachment, error) {
|
func GetAttachmentsByCommentID(commentID int64) ([]*Attachment, error) {
|
||||||
return getAttachmentsByCommentID(db.GetEngine(db.DefaultContext), commentID)
|
return GetAttachmentsByCommentIDCtx(db.DefaultContext, commentID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAttachmentsByCommentID(e db.Engine, commentID int64) ([]*Attachment, error) {
|
// GetAttachmentsByCommentIDCtx returns all attachments if comment by given ID.
|
||||||
|
func GetAttachmentsByCommentIDCtx(ctx context.Context, commentID int64) ([]*Attachment, error) {
|
||||||
attachments := make([]*Attachment, 0, 10)
|
attachments := make([]*Attachment, 0, 10)
|
||||||
return attachments, e.Where("comment_id=?", commentID).Find(&attachments)
|
return attachments, db.GetEngine(ctx).Where("comment_id=?", commentID).Find(&attachments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAttachmentByReleaseIDFileName return a file based on the the following infos:
|
// getAttachmentByReleaseIDFileName return a file based on the the following infos:
|
||||||
|
@ -229,7 +227,7 @@ func DeleteAttachmentsByComment(commentID int64, remove bool) (int, error) {
|
||||||
|
|
||||||
// UpdateAttachment updates the given attachment in database
|
// UpdateAttachment updates the given attachment in database
|
||||||
func UpdateAttachment(atta *Attachment) error {
|
func UpdateAttachment(atta *Attachment) error {
|
||||||
return updateAttachment(db.GetEngine(db.DefaultContext), atta)
|
return UpdateAttachmentCtx(db.DefaultContext, atta)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateAttachmentByUUID Updates attachment via uuid
|
// UpdateAttachmentByUUID Updates attachment via uuid
|
||||||
|
@ -241,15 +239,16 @@ func UpdateAttachmentByUUID(ctx context.Context, attach *Attachment, cols ...str
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateAttachment(e db.Engine, atta *Attachment) error {
|
// UpdateAttachmentCtx updates the given attachment in database
|
||||||
var sess *xorm.Session
|
func UpdateAttachmentCtx(ctx context.Context, atta *Attachment) error {
|
||||||
|
var sess = db.GetEngine(ctx).Cols("name", "issue_id", "release_id", "comment_id", "download_count")
|
||||||
if atta.ID != 0 && atta.UUID == "" {
|
if atta.ID != 0 && atta.UUID == "" {
|
||||||
sess = e.ID(atta.ID)
|
sess = sess.ID(atta.ID)
|
||||||
} else {
|
} else {
|
||||||
// Use uuid only if id is not set and uuid is set
|
// Use uuid only if id is not set and uuid is set
|
||||||
sess = e.Where("uuid = ?", atta.UUID)
|
sess = sess.Where("uuid = ?", atta.UUID)
|
||||||
}
|
}
|
||||||
_, err := sess.Cols("name", "issue_id", "release_id", "comment_id", "download_count").Update(atta)
|
_, err := sess.Update(atta)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package models
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unit"
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -103,30 +102,3 @@ func TestGetAttachmentsByUUIDs(t *testing.T) {
|
||||||
assert.Equal(t, int64(1), attachList[0].IssueID)
|
assert.Equal(t, int64(1), attachList[0].IssueID)
|
||||||
assert.Equal(t, int64(5), attachList[1].IssueID)
|
assert.Equal(t, int64(5), attachList[1].IssueID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLinkedRepository(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
attachID int64
|
|
||||||
expectedRepo *Repository
|
|
||||||
expectedUnitType unit.Type
|
|
||||||
}{
|
|
||||||
{"LinkedIssue", 1, &Repository{ID: 1}, unit.TypeIssues},
|
|
||||||
{"LinkedComment", 3, &Repository{ID: 1}, unit.TypePullRequests},
|
|
||||||
{"LinkedRelease", 9, &Repository{ID: 1}, unit.TypeReleases},
|
|
||||||
{"Notlinked", 10, nil, -1},
|
|
||||||
}
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
attach, err := GetAttachmentByID(tc.attachID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
repo, unitType, err := attach.LinkedRepository()
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if tc.expectedRepo != nil {
|
|
||||||
assert.Equal(t, tc.expectedRepo.ID, repo.ID)
|
|
||||||
}
|
|
||||||
assert.Equal(t, tc.expectedUnitType, unitType)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
18
models/repo/main_test.go
Normal file
18
models/repo/main_test.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
unittest.MainTest(m, filepath.Join("..", ".."),
|
||||||
|
"attachment.yml",
|
||||||
|
)
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
|
@ -224,3 +225,30 @@ func TestRepoGetReviewerTeams(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, teams, 2)
|
assert.Len(t, teams, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLinkedRepository(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
attachID int64
|
||||||
|
expectedRepo *Repository
|
||||||
|
expectedUnitType unit.Type
|
||||||
|
}{
|
||||||
|
{"LinkedIssue", 1, &Repository{ID: 1}, unit.TypeIssues},
|
||||||
|
{"LinkedComment", 3, &Repository{ID: 1}, unit.TypePullRequests},
|
||||||
|
{"LinkedRelease", 9, &Repository{ID: 1}, unit.TypeReleases},
|
||||||
|
{"Notlinked", 10, nil, -1},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
attach, err := repo_model.GetAttachmentByID(tc.attachID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
repo, unitType, err := LinkedRepository(attach)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if tc.expectedRepo != nil {
|
||||||
|
assert.Equal(t, tc.expectedRepo.ID, repo.ID)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tc.expectedUnitType, unitType)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -359,11 +359,12 @@ func IsContentEmptyErr(err error) bool {
|
||||||
|
|
||||||
// SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist
|
// SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist
|
||||||
func SubmitReview(doer *User, issue *Issue, reviewType ReviewType, content, commitID string, stale bool, attachmentUUIDs []string) (*Review, *Comment, error) {
|
func SubmitReview(doer *User, issue *Issue, reviewType ReviewType, content, commitID string, stale bool, attachmentUUIDs []string) (*Review, *Comment, error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
official := false
|
official := false
|
||||||
|
|
||||||
|
@ -429,7 +430,7 @@ func SubmitReview(doer *User, issue *Issue, reviewType ReviewType, content, comm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comm, err := createComment(sess, &CreateCommentOptions{
|
comm, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Type: CommentTypeReview,
|
Type: CommentTypeReview,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Content: review.Content,
|
Content: review.Content,
|
||||||
|
@ -464,7 +465,7 @@ func SubmitReview(doer *User, issue *Issue, reviewType ReviewType, content, comm
|
||||||
}
|
}
|
||||||
|
|
||||||
comm.Review = review
|
comm.Review = review
|
||||||
return review, comm, sess.Commit()
|
return review, comm, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetReviewersByIssueID gets the latest review of each reviewer for a pull request
|
// GetReviewersByIssueID gets the latest review of each reviewer for a pull request
|
||||||
|
@ -631,11 +632,12 @@ func InsertReviews(reviews []*Review) error {
|
||||||
|
|
||||||
// AddReviewRequest add a review request from one reviewer
|
// AddReviewRequest add a review request from one reviewer
|
||||||
func AddReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
func AddReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
review, err := getReviewByIssueIDAndUserID(sess, issue.ID, reviewer.ID)
|
review, err := getReviewByIssueIDAndUserID(sess, issue.ID, reviewer.ID)
|
||||||
if err != nil && !IsErrReviewNotExist(err) {
|
if err != nil && !IsErrReviewNotExist(err) {
|
||||||
|
@ -667,7 +669,7 @@ func AddReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
comment, err := createComment(sess, &CreateCommentOptions{
|
comment, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Type: CommentTypeReviewRequest,
|
Type: CommentTypeReviewRequest,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
@ -680,16 +682,17 @@ func AddReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return comment, sess.Commit()
|
return comment, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveReviewRequest remove a review request from one reviewer
|
// RemoveReviewRequest remove a review request from one reviewer
|
||||||
func RemoveReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
func RemoveReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
review, err := getReviewByIssueIDAndUserID(sess, issue.ID, reviewer.ID)
|
review, err := getReviewByIssueIDAndUserID(sess, issue.ID, reviewer.ID)
|
||||||
if err != nil && !IsErrReviewNotExist(err) {
|
if err != nil && !IsErrReviewNotExist(err) {
|
||||||
|
@ -721,7 +724,7 @@ func RemoveReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comment, err := createComment(sess, &CreateCommentOptions{
|
comment, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Type: CommentTypeReviewRequest,
|
Type: CommentTypeReviewRequest,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
@ -733,16 +736,17 @@ func RemoveReviewRequest(issue *Issue, reviewer, doer *User) (*Comment, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return comment, sess.Commit()
|
return comment, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTeamReviewRequest add a review request from one team
|
// AddTeamReviewRequest add a review request from one team
|
||||||
func AddTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment, error) {
|
func AddTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment, error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
review, err := getTeamReviewerByIssueIDAndTeamID(sess, issue.ID, reviewer.ID)
|
review, err := getTeamReviewerByIssueIDAndTeamID(sess, issue.ID, reviewer.ID)
|
||||||
if err != nil && !IsErrReviewNotExist(err) {
|
if err != nil && !IsErrReviewNotExist(err) {
|
||||||
|
@ -779,7 +783,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comment, err := createComment(sess, &CreateCommentOptions{
|
comment, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Type: CommentTypeReviewRequest,
|
Type: CommentTypeReviewRequest,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
@ -792,16 +796,17 @@ func AddTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment, e
|
||||||
return nil, fmt.Errorf("createComment(): %v", err)
|
return nil, fmt.Errorf("createComment(): %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return comment, sess.Commit()
|
return comment, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveTeamReviewRequest remove a review request from one team
|
// RemoveTeamReviewRequest remove a review request from one team
|
||||||
func RemoveTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment, error) {
|
func RemoveTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment, error) {
|
||||||
sess := db.NewSession(db.DefaultContext)
|
ctx, committer, err := db.TxContext()
|
||||||
defer sess.Close()
|
if err != nil {
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer committer.Close()
|
||||||
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
review, err := getTeamReviewerByIssueIDAndTeamID(sess, issue.ID, reviewer.ID)
|
review, err := getTeamReviewerByIssueIDAndTeamID(sess, issue.ID, reviewer.ID)
|
||||||
if err != nil && !IsErrReviewNotExist(err) {
|
if err != nil && !IsErrReviewNotExist(err) {
|
||||||
|
@ -836,10 +841,10 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
if doer == nil {
|
if doer == nil {
|
||||||
return nil, sess.Commit()
|
return nil, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
comment, err := createComment(sess, &CreateCommentOptions{
|
comment, err := createComment(ctx, &CreateCommentOptions{
|
||||||
Type: CommentTypeReviewRequest,
|
Type: CommentTypeReviewRequest,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
Repo: issue.Repo,
|
Repo: issue.Repo,
|
||||||
|
@ -851,7 +856,7 @@ func RemoveTeamReviewRequest(issue *Issue, reviewer *Team, doer *User) (*Comment
|
||||||
return nil, fmt.Errorf("createComment(): %v", err)
|
return nil, fmt.Errorf("createComment(): %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return comment, sess.Commit()
|
return comment, committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkConversation Add or remove Conversation mark for a code comment
|
// MarkConversation Add or remove Conversation mark for a code comment
|
||||||
|
|
|
@ -7,6 +7,7 @@ package models
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/login"
|
"code.gitea.io/gitea/models/login"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/models/webhook"
|
"code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -102,7 +103,7 @@ func GetStatistic() (stats Statistic) {
|
||||||
stats.Counter.Label, _ = e.Count(new(Label))
|
stats.Counter.Label, _ = e.Count(new(Label))
|
||||||
stats.Counter.HookTask, _ = e.Count(new(webhook.HookTask))
|
stats.Counter.HookTask, _ = e.Count(new(webhook.HookTask))
|
||||||
stats.Counter.Team, _ = e.Count(new(Team))
|
stats.Counter.Team, _ = e.Count(new(Team))
|
||||||
stats.Counter.Attachment, _ = e.Count(new(Attachment))
|
stats.Counter.Attachment, _ = e.Count(new(repo_model.Attachment))
|
||||||
stats.Counter.Project, _ = e.Count(new(Project))
|
stats.Counter.Project, _ = e.Count(new(Project))
|
||||||
stats.Counter.ProjectBoard, _ = e.Count(new(ProjectBoard))
|
stats.Counter.ProjectBoard, _ = e.Count(new(ProjectBoard))
|
||||||
return
|
return
|
||||||
|
|
|
@ -6,6 +6,7 @@ package convert
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ func ToRelease(r *models.Release) *api.Release {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToReleaseAttachment converts models.Attachment to api.Attachment
|
// ToReleaseAttachment converts models.Attachment to api.Attachment
|
||||||
func ToReleaseAttachment(a *models.Attachment) *api.Attachment {
|
func ToReleaseAttachment(a *repo_model.Attachment) *api.Attachment {
|
||||||
return &api.Attachment{
|
return &api.Attachment{
|
||||||
ID: a.ID,
|
ID: a.ID,
|
||||||
Name: a.Name,
|
Name: a.Name,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/migrations"
|
"code.gitea.io/gitea/models/migrations"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
@ -110,8 +111,8 @@ func checkDBConsistency(logger log.Logger, autofix bool) error {
|
||||||
// find attachments without existing issues or releases
|
// find attachments without existing issues or releases
|
||||||
{
|
{
|
||||||
Name: "Orphaned Attachments without existing issues or releases",
|
Name: "Orphaned Attachments without existing issues or releases",
|
||||||
Counter: models.CountOrphanedAttachments,
|
Counter: repo_model.CountOrphanedAttachments,
|
||||||
Fixer: asFixer(models.DeleteOrphanedAttachments),
|
Fixer: asFixer(repo_model.DeleteOrphanedAttachments),
|
||||||
},
|
},
|
||||||
// find null archived repositories
|
// find null archived repositories
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
package doctor
|
package doctor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/models"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,7 @@ func checkAttachmentStorageFiles(logger log.Logger, autofix bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
exist, err := models.ExistAttachmentsByUUID(stat.Name())
|
exist, err := repo_model.ExistAttachmentsByUUID(stat.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -54,7 +55,7 @@ func GetReleaseAttachment(ctx *context.APIContext) {
|
||||||
|
|
||||||
releaseID := ctx.ParamsInt64(":id")
|
releaseID := ctx.ParamsInt64(":id")
|
||||||
attachID := ctx.ParamsInt64(":asset")
|
attachID := ctx.ParamsInt64(":asset")
|
||||||
attach, err := models.GetAttachmentByID(attachID)
|
attach, err := repo_model.GetAttachmentByID(attachID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err)
|
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err)
|
||||||
return
|
return
|
||||||
|
@ -241,7 +242,7 @@ func EditReleaseAttachment(ctx *context.APIContext) {
|
||||||
// Check if release exists an load release
|
// Check if release exists an load release
|
||||||
releaseID := ctx.ParamsInt64(":id")
|
releaseID := ctx.ParamsInt64(":id")
|
||||||
attachID := ctx.ParamsInt64(":asset")
|
attachID := ctx.ParamsInt64(":asset")
|
||||||
attach, err := models.GetAttachmentByID(attachID)
|
attach, err := repo_model.GetAttachmentByID(attachID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err)
|
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err)
|
||||||
return
|
return
|
||||||
|
@ -256,7 +257,7 @@ func EditReleaseAttachment(ctx *context.APIContext) {
|
||||||
attach.Name = form.Name
|
attach.Name = form.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.UpdateAttachment(attach); err != nil {
|
if err := repo_model.UpdateAttachment(attach); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "UpdateAttachment", attach)
|
ctx.Error(http.StatusInternalServerError, "UpdateAttachment", attach)
|
||||||
}
|
}
|
||||||
ctx.JSON(http.StatusCreated, convert.ToReleaseAttachment(attach))
|
ctx.JSON(http.StatusCreated, convert.ToReleaseAttachment(attach))
|
||||||
|
@ -299,7 +300,7 @@ func DeleteReleaseAttachment(ctx *context.APIContext) {
|
||||||
// Check if release exists an load release
|
// Check if release exists an load release
|
||||||
releaseID := ctx.ParamsInt64(":id")
|
releaseID := ctx.ParamsInt64(":id")
|
||||||
attachID := ctx.ParamsInt64(":asset")
|
attachID := ctx.ParamsInt64(":asset")
|
||||||
attach, err := models.GetAttachmentByID(attachID)
|
attach, err := repo_model.GetAttachmentByID(attachID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err)
|
ctx.Error(http.StatusInternalServerError, "GetAttachmentByID", err)
|
||||||
return
|
return
|
||||||
|
@ -311,7 +312,7 @@ func DeleteReleaseAttachment(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
// FIXME Should prove the existence of the given repo, but results in unnecessary database requests
|
// FIXME Should prove the existence of the given repo, but results in unnecessary database requests
|
||||||
|
|
||||||
if err := models.DeleteAttachment(attach, true); err != nil {
|
if err := repo_model.DeleteAttachment(attach, true); err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "DeleteAttachment", err)
|
ctx.Error(http.StatusInternalServerError, "DeleteAttachment", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/httpcache"
|
"code.gitea.io/gitea/modules/httpcache"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -62,7 +63,7 @@ func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) {
|
||||||
// DeleteAttachment response for deleting issue's attachment
|
// DeleteAttachment response for deleting issue's attachment
|
||||||
func DeleteAttachment(ctx *context.Context) {
|
func DeleteAttachment(ctx *context.Context) {
|
||||||
file := ctx.FormString("file")
|
file := ctx.FormString("file")
|
||||||
attach, err := models.GetAttachmentByUUID(file)
|
attach, err := repo_model.GetAttachmentByUUID(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusBadRequest, err.Error())
|
ctx.Error(http.StatusBadRequest, err.Error())
|
||||||
return
|
return
|
||||||
|
@ -71,7 +72,7 @@ func DeleteAttachment(ctx *context.Context) {
|
||||||
ctx.Error(http.StatusForbidden)
|
ctx.Error(http.StatusForbidden)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = models.DeleteAttachment(attach, true)
|
err = repo_model.DeleteAttachment(attach, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, fmt.Sprintf("DeleteAttachment: %v", err))
|
ctx.Error(http.StatusInternalServerError, fmt.Sprintf("DeleteAttachment: %v", err))
|
||||||
return
|
return
|
||||||
|
@ -83,9 +84,9 @@ func DeleteAttachment(ctx *context.Context) {
|
||||||
|
|
||||||
// GetAttachment serve attachements
|
// GetAttachment serve attachements
|
||||||
func GetAttachment(ctx *context.Context) {
|
func GetAttachment(ctx *context.Context) {
|
||||||
attach, err := models.GetAttachmentByUUID(ctx.Params(":uuid"))
|
attach, err := repo_model.GetAttachmentByUUID(ctx.Params(":uuid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrAttachmentNotExist(err) {
|
if repo_model.IsErrAttachmentNotExist(err) {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError("GetAttachmentByUUID", err)
|
ctx.ServerError("GetAttachmentByUUID", err)
|
||||||
|
@ -93,7 +94,7 @@ func GetAttachment(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repository, unitType, err := attach.LinkedRepository()
|
repository, unitType, err := models.LinkedRepository(attach)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("LinkedRepository", err)
|
ctx.ServerError("LinkedRepository", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -2516,7 +2517,7 @@ func GetCommentAttachments(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateAttachments(item interface{}, files []string) error {
|
func updateAttachments(item interface{}, files []string) error {
|
||||||
var attachments []*models.Attachment
|
var attachments []*repo_model.Attachment
|
||||||
switch content := item.(type) {
|
switch content := item.(type) {
|
||||||
case *models.Issue:
|
case *models.Issue:
|
||||||
attachments = content.Attachments
|
attachments = content.Attachments
|
||||||
|
@ -2529,7 +2530,7 @@ func updateAttachments(item interface{}, files []string) error {
|
||||||
if util.IsStringInSlice(attachments[i].UUID, files) {
|
if util.IsStringInSlice(attachments[i].UUID, files) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := models.DeleteAttachment(attachments[i], true); err != nil {
|
if err := repo_model.DeleteAttachment(attachments[i], true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2549,16 +2550,16 @@ func updateAttachments(item interface{}, files []string) error {
|
||||||
}
|
}
|
||||||
switch content := item.(type) {
|
switch content := item.(type) {
|
||||||
case *models.Issue:
|
case *models.Issue:
|
||||||
content.Attachments, err = models.GetAttachmentsByIssueID(content.ID)
|
content.Attachments, err = repo_model.GetAttachmentsByIssueID(content.ID)
|
||||||
case *models.Comment:
|
case *models.Comment:
|
||||||
content.Attachments, err = models.GetAttachmentsByCommentID(content.ID)
|
content.Attachments, err = repo_model.GetAttachmentsByCommentID(content.ID)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown Type: %T", content)
|
return fmt.Errorf("Unknown Type: %T", content)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func attachmentsHTML(ctx *context.Context, attachments []*models.Attachment, content string) string {
|
func attachmentsHTML(ctx *context.Context, attachments []*repo_model.Attachment, content string) string {
|
||||||
attachHTML, err := ctx.HTMLString(string(tplAttachment), map[string]interface{}{
|
attachHTML, err := ctx.HTMLString(string(tplAttachment), map[string]interface{}{
|
||||||
"ctx": ctx.Data,
|
"ctx": ctx.Data,
|
||||||
"Attachments": attachments,
|
"Attachments": attachments,
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -346,7 +347,7 @@ func RedirectDownload(ctx *context.Context) {
|
||||||
curRepo := ctx.Repo.Repository
|
curRepo := ctx.Repo.Repository
|
||||||
releases, err := models.GetReleasesByRepoIDAndNames(db.DefaultContext, curRepo.ID, tagNames)
|
releases, err := models.GetReleasesByRepoIDAndNames(db.DefaultContext, curRepo.ID, tagNames)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrAttachmentNotExist(err) {
|
if repo_model.IsErrAttachmentNotExist(err) {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -355,7 +356,7 @@ func RedirectDownload(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
if len(releases) == 1 {
|
if len(releases) == 1 {
|
||||||
release := releases[0]
|
release := releases[0]
|
||||||
att, err := models.GetAttachmentByReleaseIDFileName(release.ID, fileName)
|
att, err := repo_model.GetAttachmentByReleaseIDFileName(release.ID, fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusNotFound)
|
ctx.Error(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/upload"
|
"code.gitea.io/gitea/modules/upload"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
@ -20,7 +20,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewAttachment creates a new attachment object, but do not verify.
|
// NewAttachment creates a new attachment object, but do not verify.
|
||||||
func NewAttachment(attach *models.Attachment, file io.Reader) (*models.Attachment, error) {
|
func NewAttachment(attach *repo_model.Attachment, file io.Reader) (*repo_model.Attachment, error) {
|
||||||
if attach.RepoID == 0 {
|
if attach.RepoID == 0 {
|
||||||
return nil, fmt.Errorf("attachment %s should belong to a repository", attach.Name)
|
return nil, fmt.Errorf("attachment %s should belong to a repository", attach.Name)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func NewAttachment(attach *models.Attachment, file io.Reader) (*models.Attachmen
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadAttachment upload new attachment into storage and update database
|
// UploadAttachment upload new attachment into storage and update database
|
||||||
func UploadAttachment(file io.Reader, actorID, repoID, releaseID int64, fileName string, allowedTypes string) (*models.Attachment, error) {
|
func UploadAttachment(file io.Reader, actorID, repoID, releaseID int64, fileName string, allowedTypes string) (*repo_model.Attachment, error) {
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
n, _ := util.ReadAtMost(file, buf)
|
n, _ := util.ReadAtMost(file, buf)
|
||||||
buf = buf[:n]
|
buf = buf[:n]
|
||||||
|
@ -49,7 +49,7 @@ func UploadAttachment(file io.Reader, actorID, repoID, releaseID int64, fileName
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewAttachment(&models.Attachment{
|
return NewAttachment(&repo_model.Attachment{
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
UploaderID: actorID,
|
UploaderID: actorID,
|
||||||
ReleaseID: releaseID,
|
ReleaseID: releaseID,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -29,14 +30,14 @@ func TestUploadAttachment(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
attach, err := NewAttachment(&models.Attachment{
|
attach, err := NewAttachment(&repo_model.Attachment{
|
||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
UploaderID: user.ID,
|
UploaderID: user.ID,
|
||||||
Name: filepath.Base(fPath),
|
Name: filepath.Base(fPath),
|
||||||
}, f)
|
}, f)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
attachment, err := models.GetAttachmentByUUID(attach.UUID)
|
attachment, err := repo_model.GetAttachmentByUUID(attach.UUID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, user.ID, attachment.UploaderID)
|
assert.EqualValues(t, user.ID, attachment.UploaderID)
|
||||||
assert.Equal(t, int64(0), attachment.DownloadCount)
|
assert.Equal(t, int64(0), attachment.DownloadCount)
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
base "code.gitea.io/gitea/modules/migration"
|
base "code.gitea.io/gitea/modules/migration"
|
||||||
|
@ -295,7 +296,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
|
||||||
asset.Created = release.Created
|
asset.Created = release.Created
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var attach = models.Attachment{
|
var attach = repo_model.Attachment{
|
||||||
UUID: gouuid.New().String(),
|
UUID: gouuid.New().String(),
|
||||||
Name: asset.Name,
|
Name: asset.Name,
|
||||||
DownloadCount: int64(*asset.DownloadCount),
|
DownloadCount: int64(*asset.DownloadCount),
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/notification"
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
@ -206,7 +207,7 @@ func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Relea
|
||||||
var deletedUUIDsMap = make(map[string]bool)
|
var deletedUUIDsMap = make(map[string]bool)
|
||||||
if len(delAttachmentUUIDs) > 0 {
|
if len(delAttachmentUUIDs) > 0 {
|
||||||
// Check attachments
|
// Check attachments
|
||||||
attachments, err := models.GetAttachmentsByUUIDs(ctx, delAttachmentUUIDs)
|
attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, delAttachmentUUIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %v", delAttachmentUUIDs, err)
|
return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %v", delAttachmentUUIDs, err)
|
||||||
}
|
}
|
||||||
|
@ -217,7 +218,7 @@ func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Relea
|
||||||
deletedUUIDsMap[attach.UUID] = true
|
deletedUUIDsMap[attach.UUID] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := models.DeleteAttachments(ctx, attachments, false); err != nil {
|
if _, err := repo_model.DeleteAttachments(ctx, attachments, false); err != nil {
|
||||||
return fmt.Errorf("DeleteAttachments [uuids: %v]: %v", delAttachmentUUIDs, err)
|
return fmt.Errorf("DeleteAttachments [uuids: %v]: %v", delAttachmentUUIDs, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,7 +229,7 @@ func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Relea
|
||||||
updateAttachmentsList = append(updateAttachmentsList, k)
|
updateAttachmentsList = append(updateAttachmentsList, k)
|
||||||
}
|
}
|
||||||
// Check attachments
|
// Check attachments
|
||||||
attachments, err := models.GetAttachmentsByUUIDs(ctx, updateAttachmentsList)
|
attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, updateAttachmentsList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %v", updateAttachmentsList, err)
|
return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %v", updateAttachmentsList, err)
|
||||||
}
|
}
|
||||||
|
@ -240,7 +241,7 @@ func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Relea
|
||||||
|
|
||||||
for uuid, newName := range editAttachments {
|
for uuid, newName := range editAttachments {
|
||||||
if !deletedUUIDsMap[uuid] {
|
if !deletedUUIDsMap[uuid] {
|
||||||
if err = models.UpdateAttachmentByUUID(ctx, &models.Attachment{
|
if err = repo_model.UpdateAttachmentByUUID(ctx, &repo_model.Attachment{
|
||||||
UUID: uuid,
|
UUID: uuid,
|
||||||
Name: newName,
|
Name: newName,
|
||||||
}, "name"); err != nil {
|
}, "name"); err != nil {
|
||||||
|
@ -255,7 +256,7 @@ func UpdateRelease(doer *models.User, gitRepo *git.Repository, rel *models.Relea
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, uuid := range delAttachmentUUIDs {
|
for _, uuid := range delAttachmentUUIDs {
|
||||||
if err := storage.Attachments.Delete(models.AttachmentRelativePath(uuid)); err != nil {
|
if err := storage.Attachments.Delete(repo_model.AttachmentRelativePath(uuid)); err != nil {
|
||||||
// Even delete files failed, but the attachments has been removed from database, so we
|
// Even delete files failed, but the attachments has been removed from database, so we
|
||||||
// should not return error but only record the error on logs.
|
// should not return error but only record the error on logs.
|
||||||
// users have to delete this attachments manually or we should have a
|
// users have to delete this attachments manually or we should have a
|
||||||
|
@ -321,7 +322,7 @@ func DeleteReleaseByID(id int64, doer *models.User, delTag bool) error {
|
||||||
return fmt.Errorf("LoadAttributes: %v", err)
|
return fmt.Errorf("LoadAttributes: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.DeleteAttachmentsByRelease(rel.ID); err != nil {
|
if err := repo_model.DeleteAttachmentsByRelease(rel.ID); err != nil {
|
||||||
return fmt.Errorf("DeleteAttachments: %v", err)
|
return fmt.Errorf("DeleteAttachments: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/services/attachment"
|
"code.gitea.io/gitea/services/attachment"
|
||||||
|
@ -103,7 +104,7 @@ func TestRelease_Create(t *testing.T) {
|
||||||
IsTag: false,
|
IsTag: false,
|
||||||
}, nil, ""))
|
}, nil, ""))
|
||||||
|
|
||||||
attach, err := attachment.NewAttachment(&models.Attachment{
|
attach, err := attachment.NewAttachment(&repo_model.Attachment{
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
UploaderID: user.ID,
|
UploaderID: user.ID,
|
||||||
Name: "test.txt",
|
Name: "test.txt",
|
||||||
|
@ -236,7 +237,7 @@ func TestRelease_Update(t *testing.T) {
|
||||||
assert.Equal(t, tagName, release.TagName)
|
assert.Equal(t, tagName, release.TagName)
|
||||||
|
|
||||||
// Add new attachments
|
// Add new attachments
|
||||||
attach, err := attachment.NewAttachment(&models.Attachment{
|
attach, err := attachment.NewAttachment(&repo_model.Attachment{
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
UploaderID: user.ID,
|
UploaderID: user.ID,
|
||||||
Name: "test.txt",
|
Name: "test.txt",
|
||||||
|
|
Reference in a new issue