aboutsummaryrefslogtreecommitdiff
path: root/models/issue.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/issue.go')
-rw-r--r--models/issue.go188
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.