Template
1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo synced 2024-11-29 13:16:10 +01:00

Move attachment into models/repo/ (#17650)

* Move attachment into models/repo/

* Fix test

* Fix bug
This commit is contained in:
Lunny Xiao 2021-11-19 21:39:57 +08:00 committed by GitHub
parent 7a03473159
commit fc3d082609
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 477 additions and 414 deletions

View file

@ -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
}) })

View file

@ -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

View file

@ -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
} }

View file

@ -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
} }

View file

@ -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 {

View file

@ -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)
} }

View file

@ -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()

View file

@ -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

View file

@ -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 {

View file

@ -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 {

View file

@ -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()
} }

View file

@ -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

View file

@ -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,

View file

@ -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) {

View file

@ -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 {

View file

@ -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
} }

View file

@ -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

View file

@ -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(e *xorm.Session, issue *Issue, doer *User, newProjectID int64) error { func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *User, newProjectID int64) error {
e := db.GetEngine(ctx)
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,

View file

@ -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)
} }

View file

@ -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
} }

View file

@ -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
}

View file

@ -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
} }

View file

@ -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
View 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",
)
}

View file

@ -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)
})
}
}

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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
{ {

View file

@ -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
} }

View file

@ -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
} }

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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,

View file

@ -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)

View file

@ -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),

View file

@ -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)
} }

View file

@ -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",