diff --git a/models/issue.go b/models/issue.go index f9394594b..999bd2f7a 100644 --- a/models/issue.go +++ b/models/issue.go @@ -5,6 +5,7 @@ package models import ( + "errors" "fmt" "path" "regexp" @@ -1015,9 +1016,35 @@ type NewIssueOptions struct { IsPull bool } +// GetMaxIndexOfIssue returns the max index on issue +func GetMaxIndexOfIssue(repoID int64) (int64, error) { + return getMaxIndexOfIssue(x, repoID) +} + +func getMaxIndexOfIssue(e Engine, repoID int64) (int64, error) { + var ( + maxIndex int64 + has bool + err error + ) + + has, err = e.SQL("SELECT COALESCE((SELECT MAX(`index`) FROM issue WHERE repo_id = ?),0)", repoID).Get(&maxIndex) + if err != nil { + return 0, err + } else if !has { + return 0, errors.New("Retrieve Max index from issue failed") + } + return maxIndex, nil +} + 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() + + maxIndex, err := getMaxIndexOfIssue(e, opts.Issue.RepoID) + if err != nil { + return err + } + opts.Issue.Index = maxIndex + 1 if opts.Issue.MilestoneID > 0 { milestone, err := getMilestoneByRepoID(e, opts.Issue.RepoID, opts.Issue.MilestoneID) diff --git a/models/repo.go b/models/repo.go index b37120236..3283223d5 100644 --- a/models/repo.go +++ b/models/repo.go @@ -687,13 +687,6 @@ func (repo *Repository) getUsersWithAccessMode(e Engine, mode AccessMode) (_ []* return users, nil } -// NextIssueIndex returns the next issue index -// FIXME: should have a mutex to prevent producing same index for two issues that are created -// closely enough. -func (repo *Repository) NextIssueIndex() int64 { - return int64(repo.NumIssues+repo.NumPulls) + 1 -} - var ( descPattern = regexp.MustCompile(`https?://\S+`) ) diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index dda838791..f53ab4b8f 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -251,9 +251,15 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption deadlineUnix = util.TimeStamp(form.Deadline.Unix()) } + maxIndex, err := models.GetMaxIndexOfIssue(repo.ID) + if err != nil { + ctx.ServerError("GetPatch", err) + return + } + prIssue := &models.Issue{ RepoID: repo.ID, - Index: repo.NextIssueIndex(), + Index: maxIndex + 1, Title: form.Title, PosterID: ctx.User.ID, Poster: ctx.User, diff --git a/routers/repo/pull.go b/routers/repo/pull.go index d1e2f0b0b..412750dd5 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -946,9 +946,15 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) return } + maxIndex, err := models.GetMaxIndexOfIssue(repo.ID) + if err != nil { + ctx.ServerError("GetPatch", err) + return + } + pullIssue := &models.Issue{ RepoID: repo.ID, - Index: repo.NextIssueIndex(), + Index: maxIndex + 1, Title: form.Title, PosterID: ctx.User.ID, Poster: ctx.User,