aboutsummaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/issues/comment.go13
-rw-r--r--models/issues/issue.go3
-rw-r--r--models/issues/issue_update.go11
-rw-r--r--models/migrations/migrations.go4
-rw-r--r--models/migrations/v1_23/v299.go18
5 files changed, 44 insertions, 5 deletions
diff --git a/models/issues/comment.go b/models/issues/comment.go
index 336bdde58e..c6c5dc2432 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -52,6 +52,8 @@ func (err ErrCommentNotExist) Unwrap() error {
return util.ErrNotExist
}
+var ErrCommentAlreadyChanged = util.NewInvalidArgumentErrorf("the comment is already changed")
+
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
type CommentType int
@@ -262,6 +264,7 @@ type Comment struct {
Line int64 // - previous line / + proposed line
TreePath string
Content string `xorm:"LONGTEXT"`
+ ContentVersion int `xorm:"NOT NULL DEFAULT 0"`
RenderedContent template.HTML `xorm:"-"`
// Path represents the 4 lines of code cemented by this comment
@@ -1111,7 +1114,7 @@ func UpdateCommentInvalidate(ctx context.Context, c *Comment) error {
}
// UpdateComment updates information of comment.
-func UpdateComment(ctx context.Context, c *Comment, doer *user_model.User) error {
+func UpdateComment(ctx context.Context, c *Comment, contentVersion int, doer *user_model.User) error {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
@@ -1119,9 +1122,15 @@ func UpdateComment(ctx context.Context, c *Comment, doer *user_model.User) error
defer committer.Close()
sess := db.GetEngine(ctx)
- if _, err := sess.ID(c.ID).AllCols().Update(c); err != nil {
+ c.ContentVersion = contentVersion + 1
+
+ affected, err := sess.ID(c.ID).AllCols().Where("content_version = ?", contentVersion).Update(c)
+ if err != nil {
return err
}
+ if affected == 0 {
+ return ErrCommentAlreadyChanged
+ }
if err := c.LoadIssue(ctx); err != nil {
return err
}
diff --git a/models/issues/issue.go b/models/issues/issue.go
index 87c1c86eb1..aad855522d 100644
--- a/models/issues/issue.go
+++ b/models/issues/issue.go
@@ -94,6 +94,8 @@ func (err ErrIssueWasClosed) Error() string {
return fmt.Sprintf("Issue [%d] %d was already closed", err.ID, err.Index)
}
+var ErrIssueAlreadyChanged = util.NewInvalidArgumentErrorf("the issue is already changed")
+
// Issue represents an issue or pull request of repository.
type Issue struct {
ID int64 `xorm:"pk autoincr"`
@@ -107,6 +109,7 @@ type Issue struct {
Title string `xorm:"name"`
Content string `xorm:"LONGTEXT"`
RenderedContent template.HTML `xorm:"-"`
+ ContentVersion int `xorm:"NOT NULL DEFAULT 0"`
Labels []*Label `xorm:"-"`
MilestoneID int64 `xorm:"INDEX"`
Milestone *Milestone `xorm:"-"`
diff --git a/models/issues/issue_update.go b/models/issues/issue_update.go
index 147b7eb3b9..31d76be5e0 100644
--- a/models/issues/issue_update.go
+++ b/models/issues/issue_update.go
@@ -235,7 +235,7 @@ func UpdateIssueAttachments(ctx context.Context, issueID int64, uuids []string)
}
// ChangeIssueContent changes issue content, as the given user.
-func ChangeIssueContent(ctx context.Context, issue *Issue, doer *user_model.User, content string) (err error) {
+func ChangeIssueContent(ctx context.Context, issue *Issue, doer *user_model.User, content string, contentVersion int) (err error) {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
@@ -254,9 +254,14 @@ func ChangeIssueContent(ctx context.Context, issue *Issue, doer *user_model.User
}
issue.Content = content
+ issue.ContentVersion = contentVersion + 1
- if err = UpdateIssueCols(ctx, issue, "content"); err != nil {
- return fmt.Errorf("UpdateIssueCols: %w", err)
+ affected, err := db.GetEngine(ctx).ID(issue.ID).Cols("content", "content_version").Where("content_version = ?", contentVersion).Update(issue)
+ if err != nil {
+ return err
+ }
+ if affected == 0 {
+ return ErrIssueAlreadyChanged
}
if err = SaveIssueContentHistory(ctx, doer.ID, issue.ID, 0,
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 4501585250..08882fb119 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -21,6 +21,7 @@ import (
"code.gitea.io/gitea/models/migrations/v1_20"
"code.gitea.io/gitea/models/migrations/v1_21"
"code.gitea.io/gitea/models/migrations/v1_22"
+ "code.gitea.io/gitea/models/migrations/v1_23"
"code.gitea.io/gitea/models/migrations/v1_6"
"code.gitea.io/gitea/models/migrations/v1_7"
"code.gitea.io/gitea/models/migrations/v1_8"
@@ -587,6 +588,9 @@ var migrations = []Migration{
NewMigration("Drop wrongly created table o_auth2_application", v1_22.DropWronglyCreatedTable),
// Gitea 1.22.0-rc1 ends at 299
+
+ // v299 -> v300
+ NewMigration("Add content version to issue and comment table", v1_23.AddContentVersionToIssueAndComment),
}
// GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v1_23/v299.go b/models/migrations/v1_23/v299.go
new file mode 100644
index 0000000000..f6db960c3b
--- /dev/null
+++ b/models/migrations/v1_23/v299.go
@@ -0,0 +1,18 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_23 //nolint
+
+import "xorm.io/xorm"
+
+func AddContentVersionToIssueAndComment(x *xorm.Engine) error {
+ type Issue struct {
+ ContentVersion int `xorm:"NOT NULL DEFAULT 0"`
+ }
+
+ type Comment struct {
+ ContentVersion int `xorm:"NOT NULL DEFAULT 0"`
+ }
+
+ return x.Sync(new(Comment), new(Issue))
+}