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) | ||||
| 	} | ||||
| 
 | ||||
| 	if err = issue.neuterCrossReferences(sess); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if err = issue.addCrossReferences(sess, doer); err != nil { | ||||
| 	if err = issue.addCrossReferences(sess, doer, true); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
|  | @ -790,10 +786,8 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) { | |||
| 	if err = updateIssueCols(sess, issue, "content"); err != nil { | ||||
| 		return fmt.Errorf("UpdateIssueCols: %v", err) | ||||
| 	} | ||||
| 	if err = issue.neuterCrossReferences(sess); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err = issue.addCrossReferences(sess, doer); err != nil { | ||||
| 
 | ||||
| 	if err = issue.addCrossReferences(sess, doer, true); err != nil { | ||||
| 		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 { | ||||
| 		return err | ||||
| 	} | ||||
| 	return opts.Issue.addCrossReferences(e, doer) | ||||
| 	return opts.Issue.addCrossReferences(e, doer, false) | ||||
| } | ||||
| 
 | ||||
| // NewIssue creates new issue with labels for repository.
 | ||||
|  | @ -1578,13 +1572,10 @@ func UpdateIssue(issue *Issue) error { | |||
| 	if err := updateIssue(sess, issue); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := issue.neuterCrossReferences(sess); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := issue.loadPoster(sess); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := issue.addCrossReferences(sess, issue.Poster); err != nil { | ||||
| 	if err := issue.addCrossReferences(sess, issue.Poster, true); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	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 | ||||
| 	} | ||||
| 
 | ||||
|  | @ -882,10 +882,7 @@ func UpdateComment(c *Comment, doer *User) error { | |||
| 	if err := c.loadIssue(sess); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := c.neuterCrossReferences(sess); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := c.addCrossReferences(sess, doer); err != nil { | ||||
| 	if err := c.addCrossReferences(sess, doer, true); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := sess.Commit(); err != nil { | ||||
|  |  | |||
|  | @ -25,20 +25,30 @@ type crossReferencesContext struct { | |||
| 	Doer        *User | ||||
| 	OrigIssue   *Issue | ||||
| 	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 { | ||||
| 	active := make([]*Comment, 0, 10) | ||||
| 	sess := e.Where("`ref_action` IN (?, ?, ?)", references.XRefActionNone, references.XRefActionCloses, references.XRefActionReopens). | ||||
| 		And("`ref_issue_id` = ?", issueID). | ||||
| 		And("`ref_comment_id` = ?", commentID) | ||||
| 	if err := sess.Find(&active); err != nil || len(active) == 0 { | ||||
| 	active, err := findOldCrossReferences(e, issueID, commentID) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	ids := make([]int64, len(active)) | ||||
| 	for i, c := range active { | ||||
| 		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}) | ||||
| 	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 | ||||
| 	if issue.IsPull { | ||||
| 		commentType = CommentTypePullRef | ||||
|  | @ -62,6 +72,7 @@ func (issue *Issue) addCrossReferences(e *xorm.Session, doer *User) error { | |||
| 		Type:      commentType, | ||||
| 		Doer:      doer, | ||||
| 		OrigIssue: issue, | ||||
| 		RemoveOld: removeOld, | ||||
| 	} | ||||
| 	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 { | ||||
| 		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 { | ||||
| 		var refCommentID int64 | ||||
| 		if ctx.OrigComment != nil { | ||||
|  | @ -193,10 +233,6 @@ func (issue *Issue) verifyReferencedIssue(e Engine, ctx *crossReferencesContext, | |||
| 	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 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | @ -217,6 +253,7 @@ func (comment *Comment) addCrossReferences(e *xorm.Session, doer *User) error { | |||
| 		Doer:        doer, | ||||
| 		OrigIssue:   comment.Issue, | ||||
| 		OrigComment: comment, | ||||
| 		RemoveOld:   removeOld, | ||||
| 	} | ||||
| 	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) | ||||
| 	i, err = getIssueByID(sess, i.ID) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.NoError(t, i.addCrossReferences(sess, d)) | ||||
| 	assert.NoError(t, i.addCrossReferences(sess, d, false)) | ||||
| 	assert.NoError(t, sess.Commit()) | ||||
| 	return i | ||||
| } | ||||
|  | @ -158,7 +158,7 @@ func testCreateComment(t *testing.T, repo, doer, issue int64, content string) *C | |||
| 	assert.NoError(t, sess.Begin()) | ||||
| 	_, err := sess.Insert(c) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.NoError(t, c.addCrossReferences(sess, d)) | ||||
| 	assert.NoError(t, c.addCrossReferences(sess, d, false)) | ||||
| 	assert.NoError(t, sess.Commit()) | ||||
| 	return c | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue