diff options
Diffstat (limited to 'models/issue.go')
-rw-r--r-- | models/issue.go | 188 |
1 files changed, 183 insertions, 5 deletions
diff --git a/models/issue.go b/models/issue.go index 40d3bab0..7dd69267 100644 --- a/models/issue.go +++ b/models/issue.go @@ -10,19 +10,22 @@ import ( "strings" "time" + "github.com/go-xorm/xorm" + "github.com/gogits/gogs/modules/base" ) var ( - ErrIssueNotExist = errors.New("Issue does not exist") + ErrIssueNotExist = errors.New("Issue does not exist") + ErrMilestoneNotExist = errors.New("Milestone does not exist") ) // Issue represents an issue or pull request of repository. type Issue struct { Id int64 + RepoId int64 `xorm:"INDEX"` Index int64 // Index in one repository. Name string - RepoId int64 `xorm:"INDEX"` Repo *Repository `xorm:"-"` PosterId int64 Poster *User `xorm:"-"` @@ -164,6 +167,8 @@ type IssueUser struct { Uid int64 // User ID. IssueId int64 RepoId int64 + MilestoneId int64 + Labels string `xorm:"TEXT"` IsRead bool IsAssigned bool IsMentioned bool @@ -280,9 +285,10 @@ const ( func GetIssueStats(rid, uid int64, isShowClosed bool, filterMode int) *IssueStats { stats := &IssueStats{} issue := new(Issue) + tmpSess := &xorm.Session{} sess := orm.Where("repo_id=?", rid) - tmpSess := sess + *tmpSess = *sess stats.OpenCount, _ = tmpSess.And("is_closed=?", false).Count(issue) *tmpSess = *sess stats.ClosedCount, _ = tmpSess.And("is_closed=?", true).Count(issue) @@ -390,7 +396,7 @@ func UpdateIssueUserPairsByMentions(uids []int64, iid int64) error { // Label represents a label of repository for issues. type Label struct { Id int64 - Rid int64 `xorm:"INDEX"` + RepoId int64 `xorm:"INDEX"` Name string Color string NumIssues int @@ -401,17 +407,189 @@ type Label struct { // Milestone represents a milestone of repository. type Milestone struct { Id int64 - Rid int64 `xorm:"INDEX"` + RepoId int64 `xorm:"INDEX"` + Index int64 Name string Content string + RenderedContent string `xorm:"-"` IsClosed bool NumIssues int NumClosedIssues int + NumOpenIssues int `xorm:"-"` Completeness int // Percentage(1-100). Deadline time.Time + DeadlineString string `xorm:"-"` ClosedDate time.Time } +// CalOpenIssues calculates the open issues of milestone. +func (m *Milestone) CalOpenIssues() { + m.NumOpenIssues = m.NumIssues - m.NumClosedIssues +} + +// NewMilestone creates new milestone of repository. +func NewMilestone(m *Milestone) (err error) { + sess := orm.NewSession() + defer sess.Close() + if err = sess.Begin(); err != nil { + return err + } + + if _, err = sess.Insert(m); err != nil { + sess.Rollback() + return err + } + + rawSql := "UPDATE `repository` SET num_milestones = num_milestones + 1 WHERE id = ?" + if _, err = sess.Exec(rawSql, m.RepoId); err != nil { + sess.Rollback() + return err + } + return sess.Commit() +} + +// GetMilestoneById returns the milestone by given ID. +func GetMilestoneById(id int64) (*Milestone, error) { + m := &Milestone{Id: id} + has, err := orm.Get(m) + if err != nil { + return nil, err + } else if !has { + return nil, ErrMilestoneNotExist + } + return m, nil +} + +// GetMilestoneByIndex returns the milestone of given repository and index. +func GetMilestoneByIndex(repoId, idx int64) (*Milestone, error) { + m := &Milestone{RepoId: repoId, Index: idx} + has, err := orm.Get(m) + if err != nil { + return nil, err + } else if !has { + return nil, ErrMilestoneNotExist + } + return m, nil +} + +// GetMilestones returns a list of milestones of given repository and status. +func GetMilestones(repoId int64, isClosed bool) ([]*Milestone, error) { + miles := make([]*Milestone, 0, 10) + err := orm.Where("repo_id=?", repoId).And("is_closed=?", isClosed).Find(&miles) + return miles, err +} + +// UpdateMilestone updates information of given milestone. +func UpdateMilestone(m *Milestone) error { + _, err := orm.Id(m.Id).Update(m) + return err +} + +// ChangeMilestoneStatus changes the milestone open/closed status. +func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) { + repo, err := GetRepositoryById(m.RepoId) + if err != nil { + return err + } + + sess := orm.NewSession() + defer sess.Close() + if err = sess.Begin(); err != nil { + return err + } + + m.IsClosed = isClosed + if _, err = sess.Id(m.Id).AllCols().Update(m); err != nil { + sess.Rollback() + return err + } + + if isClosed { + repo.NumClosedMilestones++ + } else { + repo.NumClosedMilestones-- + } + if _, err = sess.Id(repo.Id).Update(repo); err != nil { + sess.Rollback() + return err + } + return sess.Commit() +} + +// ChangeMilestoneAssign changes assignment of milestone for issue. +func ChangeMilestoneAssign(oldMid, mid int64, isIssueClosed bool) (err error) { + sess := orm.NewSession() + defer sess.Close() + if err = sess.Begin(); err != nil { + return err + } + + if oldMid > 0 { + m, err := GetMilestoneById(oldMid) + if err != nil { + return err + } + + m.NumIssues-- + if isIssueClosed { + m.NumClosedIssues-- + } + if m.NumIssues > 0 { + m.Completeness = m.NumClosedIssues * 100 / m.NumIssues + } else { + m.Completeness = 0 + } + if _, err = sess.Id(m.Id).Update(m); err != nil { + sess.Rollback() + return err + } + } + + if mid > 0 { + m, err := GetMilestoneById(mid) + if err != nil { + return err + } + m.NumIssues++ + if isIssueClosed { + m.NumClosedIssues++ + } + m.Completeness = m.NumClosedIssues * 100 / m.NumIssues + if _, err = sess.Id(m.Id).Update(m); err != nil { + sess.Rollback() + return err + } + } + return sess.Commit() +} + +// DeleteMilestone deletes a milestone. +func DeleteMilestone(m *Milestone) (err error) { + sess := orm.NewSession() + defer sess.Close() + if err = sess.Begin(); err != nil { + return err + } + + if _, err = sess.Delete(m); err != nil { + sess.Rollback() + return err + } + + rawSql := "UPDATE `repository` SET num_milestones = num_milestones - 1 WHERE id = ?" + if _, err = sess.Exec(rawSql, m.RepoId); err != nil { + sess.Rollback() + return err + } + + rawSql = "UPDATE `issue` SET milestone_id = 0 WHERE milestone_id = ?" + if _, err = sess.Exec(rawSql, m.Id); err != nil { + sess.Rollback() + return err + } + return sess.Commit() +} + // Issue types. const ( IT_PLAIN = iota // Pure comment. |