Avoid re-issuing redundant cross-references. (#8734)
* Avoid re-issuing redundant cross-references. * Remove unused func; fix lint * Simplify code as suggested by @laftriks * Update test
This commit is contained in:
parent
f128e06ea6
commit
2c2b9718e6
4 changed files with 57 additions and 32 deletions
|
@ -722,11 +722,7 @@ func (issue *Issue) ChangeTitle(doer *User, oldTitle string) (err error) {
|
||||||
return fmt.Errorf("createComment: %v", err)
|
return fmt.Errorf("createComment: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.neuterCrossReferences(sess); err != nil {
|
if err = issue.addCrossReferences(sess, doer, true); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = issue.addCrossReferences(sess, doer); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,10 +786,8 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
|
||||||
if err = updateIssueCols(sess, issue, "content"); err != nil {
|
if err = updateIssueCols(sess, issue, "content"); err != nil {
|
||||||
return fmt.Errorf("UpdateIssueCols: %v", err)
|
return fmt.Errorf("UpdateIssueCols: %v", err)
|
||||||
}
|
}
|
||||||
if err = issue.neuterCrossReferences(sess); err != nil {
|
|
||||||
return err
|
if err = issue.addCrossReferences(sess, doer, true); err != nil {
|
||||||
}
|
|
||||||
if err = issue.addCrossReferences(sess, doer); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,7 +938,7 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
|
||||||
if err = opts.Issue.loadAttributes(e); err != nil {
|
if err = opts.Issue.loadAttributes(e); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return opts.Issue.addCrossReferences(e, doer)
|
return opts.Issue.addCrossReferences(e, doer, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIssue creates new issue with labels for repository.
|
// NewIssue creates new issue with labels for repository.
|
||||||
|
@ -1578,13 +1572,10 @@ func UpdateIssue(issue *Issue) error {
|
||||||
if err := updateIssue(sess, issue); err != nil {
|
if err := updateIssue(sess, issue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := issue.neuterCrossReferences(sess); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := issue.loadPoster(sess); err != nil {
|
if err := issue.loadPoster(sess); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := issue.addCrossReferences(sess, issue.Poster); err != nil {
|
if err := issue.addCrossReferences(sess, issue.Poster, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return sess.Commit()
|
return sess.Commit()
|
||||||
|
|
|
@ -545,7 +545,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = comment.addCrossReferences(e, opts.Doer); err != nil {
|
if err = comment.addCrossReferences(e, opts.Doer, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,10 +882,7 @@ 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.neuterCrossReferences(sess); err != nil {
|
if err := c.addCrossReferences(sess, doer, true); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := c.addCrossReferences(sess, doer); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := sess.Commit(); err != nil {
|
if err := sess.Commit(); err != nil {
|
||||||
|
|
|
@ -25,20 +25,30 @@ type crossReferencesContext struct {
|
||||||
Doer *User
|
Doer *User
|
||||||
OrigIssue *Issue
|
OrigIssue *Issue
|
||||||
OrigComment *Comment
|
OrigComment *Comment
|
||||||
|
RemoveOld bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func findOldCrossReferences(e Engine, issueID int64, commentID int64) ([]*Comment, error) {
|
||||||
|
active := make([]*Comment, 0, 10)
|
||||||
|
return active, e.Where("`ref_action` IN (?, ?, ?)", references.XRefActionNone, references.XRefActionCloses, references.XRefActionReopens).
|
||||||
|
And("`ref_issue_id` = ?", issueID).
|
||||||
|
And("`ref_comment_id` = ?", commentID).
|
||||||
|
Find(&active)
|
||||||
}
|
}
|
||||||
|
|
||||||
func neuterCrossReferences(e Engine, issueID int64, commentID int64) error {
|
func neuterCrossReferences(e Engine, issueID int64, commentID int64) error {
|
||||||
active := make([]*Comment, 0, 10)
|
active, err := findOldCrossReferences(e, issueID, commentID)
|
||||||
sess := e.Where("`ref_action` IN (?, ?, ?)", references.XRefActionNone, references.XRefActionCloses, references.XRefActionReopens).
|
if err != nil {
|
||||||
And("`ref_issue_id` = ?", issueID).
|
|
||||||
And("`ref_comment_id` = ?", commentID)
|
|
||||||
if err := sess.Find(&active); err != nil || len(active) == 0 {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ids := make([]int64, len(active))
|
ids := make([]int64, len(active))
|
||||||
for i, c := range active {
|
for i, c := range active {
|
||||||
ids[i] = c.ID
|
ids[i] = c.ID
|
||||||
}
|
}
|
||||||
|
return neuterCrossReferencesIds(e, ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
func neuterCrossReferencesIds(e Engine, ids []int64) error {
|
||||||
_, err := e.In("id", ids).Cols("`ref_action`").Update(&Comment{RefAction: references.XRefActionNeutered})
|
_, err := e.In("id", ids).Cols("`ref_action`").Update(&Comment{RefAction: references.XRefActionNeutered})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -51,7 +61,7 @@ func neuterCrossReferences(e Engine, issueID int64, commentID int64) error {
|
||||||
// \/ \/ \/
|
// \/ \/ \/
|
||||||
//
|
//
|
||||||
|
|
||||||
func (issue *Issue) addCrossReferences(e *xorm.Session, doer *User) error {
|
func (issue *Issue) addCrossReferences(e *xorm.Session, doer *User, removeOld bool) error {
|
||||||
var commentType CommentType
|
var commentType CommentType
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
commentType = CommentTypePullRef
|
commentType = CommentTypePullRef
|
||||||
|
@ -62,6 +72,7 @@ func (issue *Issue) addCrossReferences(e *xorm.Session, doer *User) error {
|
||||||
Type: commentType,
|
Type: commentType,
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
OrigIssue: issue,
|
OrigIssue: issue,
|
||||||
|
RemoveOld: removeOld,
|
||||||
}
|
}
|
||||||
return issue.createCrossReferences(e, ctx, issue.Title, issue.Content)
|
return issue.createCrossReferences(e, ctx, issue.Title, issue.Content)
|
||||||
}
|
}
|
||||||
|
@ -71,6 +82,35 @@ func (issue *Issue) createCrossReferences(e *xorm.Session, ctx *crossReferencesC
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if ctx.RemoveOld {
|
||||||
|
var commentID int64
|
||||||
|
if ctx.OrigComment != nil {
|
||||||
|
commentID = ctx.OrigComment.ID
|
||||||
|
}
|
||||||
|
active, err := findOldCrossReferences(e, ctx.OrigIssue.ID, commentID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ids := make([]int64, 0, len(active))
|
||||||
|
for _, c := range active {
|
||||||
|
found := false
|
||||||
|
for i, x := range xreflist {
|
||||||
|
if x.Issue.ID == c.IssueID && x.Action == c.RefAction {
|
||||||
|
found = true
|
||||||
|
xreflist = append(xreflist[:i], xreflist[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
ids = append(ids, c.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(ids) > 0 {
|
||||||
|
if err = neuterCrossReferencesIds(e, ids); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, xref := range xreflist {
|
for _, xref := range xreflist {
|
||||||
var refCommentID int64
|
var refCommentID int64
|
||||||
if ctx.OrigComment != nil {
|
if ctx.OrigComment != nil {
|
||||||
|
@ -193,10 +233,6 @@ func (issue *Issue) verifyReferencedIssue(e Engine, ctx *crossReferencesContext,
|
||||||
return refIssue, refAction, nil
|
return refIssue, refAction, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) neuterCrossReferences(e Engine) error {
|
|
||||||
return neuterCrossReferences(e, issue.ID, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// _________ __
|
// _________ __
|
||||||
// \_ ___ \ ____ _____ _____ ____ _____/ |_
|
// \_ ___ \ ____ _____ _____ ____ _____/ |_
|
||||||
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
|
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
|
||||||
|
@ -205,7 +241,7 @@ func (issue *Issue) neuterCrossReferences(e Engine) error {
|
||||||
// \/ \/ \/ \/ \/
|
// \/ \/ \/ \/ \/
|
||||||
//
|
//
|
||||||
|
|
||||||
func (comment *Comment) addCrossReferences(e *xorm.Session, doer *User) error {
|
func (comment *Comment) addCrossReferences(e *xorm.Session, doer *User, removeOld bool) error {
|
||||||
if comment.Type != CommentTypeCode && comment.Type != CommentTypeComment {
|
if comment.Type != CommentTypeCode && comment.Type != CommentTypeComment {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -217,6 +253,7 @@ func (comment *Comment) addCrossReferences(e *xorm.Session, doer *User) error {
|
||||||
Doer: doer,
|
Doer: doer,
|
||||||
OrigIssue: comment.Issue,
|
OrigIssue: comment.Issue,
|
||||||
OrigComment: comment,
|
OrigComment: comment,
|
||||||
|
RemoveOld: removeOld,
|
||||||
}
|
}
|
||||||
return comment.Issue.createCrossReferences(e, ctx, "", comment.Content)
|
return comment.Issue.createCrossReferences(e, ctx, "", comment.Content)
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,7 @@ func testCreateIssue(t *testing.T, repo, doer int64, title, content string, ispu
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
i, err = getIssueByID(sess, i.ID)
|
i, err = getIssueByID(sess, i.ID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, i.addCrossReferences(sess, d))
|
assert.NoError(t, i.addCrossReferences(sess, d, false))
|
||||||
assert.NoError(t, sess.Commit())
|
assert.NoError(t, sess.Commit())
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ func testCreateComment(t *testing.T, repo, doer, issue int64, content string) *C
|
||||||
assert.NoError(t, sess.Begin())
|
assert.NoError(t, sess.Begin())
|
||||||
_, err := sess.Insert(c)
|
_, err := sess.Insert(c)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, c.addCrossReferences(sess, d))
|
assert.NoError(t, c.addCrossReferences(sess, d, false))
|
||||||
assert.NoError(t, sess.Commit())
|
assert.NoError(t, sess.Commit())
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue