diff --git a/models/issue.go b/models/issue.go index 1727da1d50..05b17e4da5 100644 --- a/models/issue.go +++ b/models/issue.go @@ -739,7 +739,7 @@ type NewIssueOptions struct { IsPull bool } -func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) { +func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) { opts.Issue.Title = strings.TrimSpace(opts.Issue.Title) opts.Issue.Index = opts.Repo.NextIssueIndex() @@ -754,9 +754,6 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) { if milestone != nil { opts.Issue.MilestoneID = milestone.ID opts.Issue.Milestone = milestone - if err = changeMilestoneAssign(e, opts.Issue, -1); err != nil { - return err - } } } @@ -785,6 +782,12 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) { return err } + if opts.Issue.MilestoneID > 0 { + if err = changeMilestoneAssign(e, doer, opts.Issue, -1); err != nil { + return err + } + } + if opts.IsPull { _, err = e.Exec("UPDATE `repository` SET num_pulls = num_pulls + 1 WHERE id = ?", opts.Issue.RepoID) } else { @@ -849,7 +852,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) return err } - if err = newIssue(sess, NewIssueOptions{ + if err = newIssue(sess, issue.Poster, NewIssueOptions{ Repo: repo, Issue: issue, LableIDs: labelIDs, @@ -1773,7 +1776,7 @@ func ChangeMilestoneIssueStats(issue *Issue) (err error) { return sess.Commit() } -func changeMilestoneAssign(e *xorm.Session, issue *Issue, oldMilestoneID int64) error { +func changeMilestoneAssign(e *xorm.Session, doer *User, issue *Issue, oldMilestoneID int64) error { if oldMilestoneID > 0 { m, err := getMilestoneByRepoID(e, issue.RepoID, oldMilestoneID) if err != nil { @@ -1810,18 +1813,28 @@ func changeMilestoneAssign(e *xorm.Session, issue *Issue, oldMilestoneID int64) } } + if err := issue.loadRepo(e); err != nil { + return err + } + + if oldMilestoneID > 0 || issue.MilestoneID > 0 { + if _, err := createMilestoneComment(e, doer, issue.Repo, issue, oldMilestoneID, issue.MilestoneID); err != nil { + return err + } + } + return updateIssue(e, issue) } // ChangeMilestoneAssign changes assignment of milestone for issue. -func ChangeMilestoneAssign(issue *Issue, oldMilestoneID int64) (err error) { +func ChangeMilestoneAssign(issue *Issue, doer *User, oldMilestoneID int64) (err error) { sess := x.NewSession() defer sess.Close() if err = sess.Begin(); err != nil { return err } - if err = changeMilestoneAssign(sess, issue, oldMilestoneID); err != nil { + if err = changeMilestoneAssign(sess, doer, issue, oldMilestoneID); err != nil { return err } return sess.Commit() diff --git a/models/issue_comment.go b/models/issue_comment.go index be7044a8e7..d128e2ebab 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -38,6 +38,8 @@ const ( CommentTypePullRef // Labels changed CommentTypeLabel + // Milestone changed + CommentTypeMilestone ) // CommentTag defines comment tag type @@ -58,9 +60,13 @@ type Comment struct { PosterID int64 `xorm:"INDEX"` Poster *User `xorm:"-"` IssueID int64 `xorm:"INDEX"` - CommitID int64 LabelID int64 Label *Label `xorm:"-"` + OldMilestoneID int64 + MilestoneID int64 + OldMilestone *Milestone `xorm:"-"` + Milestone *Milestone `xorm:"-"` + CommitID int64 Line int64 Content string `xorm:"TEXT"` RenderedContent string `xorm:"-"` @@ -204,6 +210,36 @@ func (c *Comment) LoadLabel() error { return nil } +// LoadMilestone if comment.Type is CommentTypeMilestone, then load milestone +func (c *Comment) LoadMilestone() error { + if c.OldMilestoneID > 0 { + var oldMilestone Milestone + has, err := x.ID(c.OldMilestoneID).Get(&oldMilestone) + if err != nil { + return err + } else if !has { + return ErrMilestoneNotExist{ + ID: c.OldMilestoneID, + } + } + c.OldMilestone = &oldMilestone + } + + if c.MilestoneID > 0 { + var milestone Milestone + has, err := x.ID(c.MilestoneID).Get(&milestone) + if err != nil { + return err + } else if !has { + return ErrMilestoneNotExist{ + ID: c.MilestoneID, + } + } + c.Milestone = &milestone + } + return nil +} + // MailParticipants sends new comment emails to repository watchers // and mentioned people. func (c *Comment) MailParticipants(e Engine, opType ActionType, issue *Issue) (err error) { @@ -233,15 +269,17 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err LabelID = opts.Label.ID } comment := &Comment{ - Type: opts.Type, - PosterID: opts.Doer.ID, - Poster: opts.Doer, - IssueID: opts.Issue.ID, - LabelID: LabelID, - CommitID: opts.CommitID, - CommitSHA: opts.CommitSHA, - Line: opts.LineNum, - Content: opts.Content, + Type: opts.Type, + PosterID: opts.Doer.ID, + Poster: opts.Doer, + IssueID: opts.Issue.ID, + LabelID: LabelID, + OldMilestoneID: opts.OldMilestoneID, + MilestoneID: opts.MilestoneID, + CommitID: opts.CommitID, + CommitSHA: opts.CommitSHA, + Line: opts.LineNum, + Content: opts.Content, } if _, err = e.Insert(comment); err != nil { return nil, err @@ -367,6 +405,17 @@ func createLabelComment(e *xorm.Session, doer *User, repo *Repository, issue *Is }) } +func createMilestoneComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, oldMilestoneID, milestoneID int64) (*Comment, error) { + return createComment(e, &CreateCommentOptions{ + Type: CommentTypeMilestone, + Doer: doer, + Repo: repo, + Issue: issue, + OldMilestoneID: oldMilestoneID, + MilestoneID: milestoneID, + }) +} + // CreateCommentOptions defines options for creating comment type CreateCommentOptions struct { Type CommentType @@ -375,11 +424,13 @@ type CreateCommentOptions struct { Issue *Issue Label *Label - CommitID int64 - CommitSHA string - LineNum int64 - Content string - Attachments []string // UUIDs of attachments + OldMilestoneID int64 + MilestoneID int64 + CommitID int64 + CommitSHA string + LineNum int64 + Content string + Attachments []string // UUIDs of attachments } // CreateComment creates comment of issue or commit. diff --git a/models/pull.go b/models/pull.go index 382738bf29..e680480978 100644 --- a/models/pull.go +++ b/models/pull.go @@ -470,7 +470,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str return err } - if err = newIssue(sess, NewIssueOptions{ + if err = newIssue(sess, pull.Poster, NewIssueOptions{ Repo: repo, Issue: pull, LableIDs: labelIDs, diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 546b9489b1..cd2b67f8da 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -543,6 +543,9 @@ issues.label_templates.use = Use this label set issues.label_templates.fail_to_load_file = Failed to load label template file '%s': %v issues.add_label_at = `added the