- Fill Milestone and Assignee field when available in webhook payloadtags/v1.2.0-rc1
| @@ -19,7 +19,7 @@ github.com/go-xorm/xorm = commit:c6c7056 | |||
| github.com/gogits/chardet = commit:2404f77 | |||
| github.com/gogits/cron = commit:7f3990a | |||
| github.com/gogits/git-module = commit:f78bf3b | |||
| github.com/gogits/go-gogs-client = commit:e363d3f | |||
| github.com/gogits/go-gogs-client = commit:51c4df8 | |||
| github.com/issue9/identicon = commit:d36b545 | |||
| github.com/jaytaylor/html2text = commit:52d9b78 | |||
| github.com/kardianos/minwinsvc = commit:cad6b2b | |||
| @@ -3,7 +3,7 @@ Gogs - Go Git Service [ | |||
| ##### Current tip version: 0.9.81 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||
| ##### Current tip version: 0.9.82 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||
| | Web | UI | Preview | | |||
| |:-------------:|:-------:|:-------:| | |||
| @@ -88,8 +88,8 @@ func checkVersion() { | |||
| {"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"}, | |||
| {"gopkg.in/ini.v1", ini.Version, "1.8.4"}, | |||
| {"gopkg.in/macaron.v1", macaron.Version, "1.1.7"}, | |||
| {"github.com/gogits/git-module", git.Version, "0.3.6"}, | |||
| {"github.com/gogits/go-gogs-client", gogs.Version, "0.12.0"}, | |||
| {"github.com/gogits/git-module", git.Version, "0.3.7"}, | |||
| {"github.com/gogits/go-gogs-client", gogs.Version, "0.12.1"}, | |||
| } | |||
| for _, c := range checkers { | |||
| if !version.Compare(c.Version(), c.Expected, ">=") { | |||
| @@ -43,7 +43,7 @@ imports: | |||
| - name: github.com/gogits/git-module | |||
| version: f78bf3bf703cb3eb0e85a9475d26826939feda4f | |||
| - name: github.com/gogits/go-gogs-client | |||
| version: e363d3ff8f70d0fe813324eedf228684af41c29c | |||
| version: 51c4df8c350b32f095c8eb236aae2e306025eead | |||
| - name: github.com/issue9/identicon | |||
| version: d36b54562f4cf70c83653e13dc95c220c79ef521 | |||
| - name: github.com/jaytaylor/html2text | |||
| @@ -17,7 +17,7 @@ import ( | |||
| "github.com/gogits/gogs/modules/setting" | |||
| ) | |||
| const APP_VER = "0.9.81.0816" | |||
| const APP_VER = "0.9.82.0816" | |||
| func init() { | |||
| runtime.GOMAXPROCS(runtime.NumCPU()) | |||
| @@ -520,7 +520,7 @@ func CommitRepoAction( | |||
| Before: oldCommitID, | |||
| After: newCommitID, | |||
| CompareURL: setting.AppUrl + commit.CompareURL, | |||
| Commits: commit.ToApiPayloadCommits(repo.FullLink()), | |||
| Commits: commit.ToApiPayloadCommits(repo.HTMLURL()), | |||
| Repo: apiRepo, | |||
| Pusher: apiPusher, | |||
| Sender: apiPusher, | |||
| @@ -32,23 +32,23 @@ var ( | |||
| type Issue struct { | |||
| ID int64 `xorm:"pk autoincr"` | |||
| RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"` | |||
| Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository. | |||
| Title string `xorm:"name"` | |||
| Repo *Repository `xorm:"-"` | |||
| Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository. | |||
| PosterID int64 | |||
| Poster *User `xorm:"-"` | |||
| Title string `xorm:"name"` | |||
| Content string `xorm:"TEXT"` | |||
| RenderedContent string `xorm:"-"` | |||
| Labels []*Label `xorm:"-"` | |||
| MilestoneID int64 | |||
| Milestone *Milestone `xorm:"-"` | |||
| Priority int | |||
| AssigneeID int64 | |||
| Assignee *User `xorm:"-"` | |||
| IsRead bool `xorm:"-"` | |||
| IsPull bool // Indicates whether is a pull request or not. | |||
| *PullRequest `xorm:"-"` | |||
| IsClosed bool | |||
| Content string `xorm:"TEXT"` | |||
| RenderedContent string `xorm:"-"` | |||
| Priority int | |||
| IsRead bool `xorm:"-"` | |||
| IsPull bool // Indicates whether is a pull request or not. | |||
| PullRequest *PullRequest `xorm:"-"` | |||
| NumComments int | |||
| Deadline time.Time `xorm:"-"` | |||
| @@ -155,6 +155,16 @@ func (issue *Issue) LoadAttributes() error { | |||
| return issue.loadAttributes(x) | |||
| } | |||
| func (issue *Issue) HTMLURL() string { | |||
| var path string | |||
| if issue.IsPull { | |||
| path = "pulls" | |||
| } else { | |||
| path = "issues" | |||
| } | |||
| return fmt.Sprintf("%s/%s/%d", issue.Repo.HTMLURL(), path, issue.Index) | |||
| } | |||
| // State returns string representation of issue status. | |||
| func (i *Issue) State() api.StateType { | |||
| if i.IsClosed { | |||
| @@ -175,11 +185,11 @@ func (issue *Issue) APIFormat() *api.Issue { | |||
| apiIssue := &api.Issue{ | |||
| ID: issue.ID, | |||
| Index: issue.Index, | |||
| State: issue.State(), | |||
| Poster: issue.Poster.APIFormat(), | |||
| Title: issue.Title, | |||
| Body: issue.Content, | |||
| User: issue.Poster.APIFormat(), | |||
| Labels: apiLabels, | |||
| State: issue.State(), | |||
| Comments: issue.NumComments, | |||
| Created: issue.Created, | |||
| Updated: issue.Updated, | |||
| @@ -208,16 +218,6 @@ func (i *Issue) HashTag() string { | |||
| return "issue-" + com.ToStr(i.ID) | |||
| } | |||
| func (issue *Issue) FullLink() string { | |||
| var path string | |||
| if issue.IsPull { | |||
| path = "pulls" | |||
| } else { | |||
| path = "issues" | |||
| } | |||
| return fmt.Sprintf("%s/%s/%d", issue.Repo.FullLink(), path, issue.Index) | |||
| } | |||
| // IsPoster returns true if given user by ID is the poster. | |||
| func (i *Issue) IsPoster(uid int64) bool { | |||
| return i.PosterID == uid | |||
| @@ -591,16 +591,44 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) { | |||
| opts.Issue.Title = strings.TrimSpace(opts.Issue.Title) | |||
| opts.Issue.Index = opts.Repo.NextIssueIndex() | |||
| if opts.Issue.MilestoneID > 0 { | |||
| milestone, err := getMilestoneByID(e, opts.Issue.MilestoneID) | |||
| if err != nil && !IsErrMilestoneNotExist(err) { | |||
| return fmt.Errorf("getMilestoneByID: %v", err) | |||
| } | |||
| // Assume milestone is invalid and drop silently. | |||
| opts.Issue.MilestoneID = 0 | |||
| if milestone != nil { | |||
| opts.Issue.MilestoneID = milestone.ID | |||
| opts.Issue.Milestone = milestone | |||
| if err = changeMilestoneAssign(e, opts.Issue, -1); err != nil { | |||
| return err | |||
| } | |||
| } | |||
| } | |||
| if opts.Issue.AssigneeID > 0 { | |||
| // Silently drop invalid assignee. | |||
| valid, err := hasAccess(e, &User{ID: opts.Issue.AssigneeID}, opts.Repo, ACCESS_MODE_WRITE) | |||
| if err != nil { | |||
| return fmt.Errorf("hasAccess [user_id: %d, repo_id: %d]: %v", opts.Issue.AssigneeID, opts.Repo.ID, err) | |||
| } else if !valid { | |||
| opts.Issue.AssigneeID = 0 | |||
| assignee, err := getUserByID(e, opts.Issue.AssigneeID) | |||
| if err != nil && !IsErrUserNotExist(err) { | |||
| return fmt.Errorf("getUserByID: %v", err) | |||
| } | |||
| // Assume assignee is invalid and drop silently. | |||
| opts.Issue.AssigneeID = 0 | |||
| if assignee != nil { | |||
| valid, err := hasAccess(e, assignee, opts.Repo, ACCESS_MODE_WRITE) | |||
| if err != nil { | |||
| return fmt.Errorf("hasAccess [user_id: %d, repo_id: %d]: %v", assignee.ID, opts.Repo.ID, err) | |||
| } | |||
| if valid { | |||
| opts.Issue.AssigneeID = assignee.ID | |||
| opts.Issue.Assignee = assignee | |||
| } | |||
| } | |||
| } | |||
| // Milestone and assignee validation should happen before insert actual object. | |||
| if _, err = e.Insert(opts.Issue); err != nil { | |||
| return err | |||
| } | |||
| @@ -634,12 +662,6 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) { | |||
| } | |||
| } | |||
| if opts.Issue.MilestoneID > 0 { | |||
| if err = changeMilestoneAssign(e, opts.Issue, -1); err != nil { | |||
| return err | |||
| } | |||
| } | |||
| if err = newIssueUsers(e, opts.Repo, opts.Issue); err != nil { | |||
| return err | |||
| } | |||
| @@ -129,7 +129,7 @@ func SendCollaboratorMail(u, doer *User, repo *Repository) { | |||
| data := map[string]interface{}{ | |||
| "Subject": subject, | |||
| "RepoName": repoName, | |||
| "Link": repo.FullLink(), | |||
| "Link": repo.HTMLURL(), | |||
| } | |||
| body, err := mailRender.HTMLString(string(MAIL_NOTIFY_COLLABORATOR), data) | |||
| if err != nil { | |||
| @@ -153,8 +153,8 @@ func composeTplData(subject, body, link string) map[string]interface{} { | |||
| func composeIssueMessage(issue *Issue, doer *User, tplName base.TplName, tos []string, info string) *mailer.Message { | |||
| subject := issue.MailSubject() | |||
| body := string(markdown.RenderSpecialLink([]byte(issue.Content), issue.Repo.FullLink(), issue.Repo.ComposeMetas())) | |||
| data := composeTplData(subject, body, issue.FullLink()) | |||
| body := string(markdown.RenderSpecialLink([]byte(issue.Content), issue.Repo.HTMLURL(), issue.Repo.ComposeMetas())) | |||
| data := composeTplData(subject, body, issue.HTMLURL()) | |||
| data["Doer"] = doer | |||
| content, err := mailRender.HTMLString(string(tplName), data) | |||
| if err != nil { | |||
| @@ -100,6 +100,10 @@ func (pr *PullRequest) LoadAttributes() error { | |||
| } | |||
| func (pr *PullRequest) LoadIssue() (err error) { | |||
| if pr.Issue != nil { | |||
| return nil | |||
| } | |||
| pr.Issue, err = GetIssueByID(pr.IssueID) | |||
| return err | |||
| } | |||
| @@ -112,14 +116,15 @@ func (pr *PullRequest) APIFormat() *api.PullRequest { | |||
| apiPullRequest := &api.PullRequest{ | |||
| ID: pr.ID, | |||
| Index: pr.Index, | |||
| State: apiIssue.State, | |||
| Poster: apiIssue.Poster, | |||
| Title: apiIssue.Title, | |||
| Body: apiIssue.Body, | |||
| User: apiIssue.User, | |||
| Labels: apiIssue.Labels, | |||
| Milestone: apiIssue.Milestone, | |||
| Assignee: apiIssue.Assignee, | |||
| State: apiIssue.State, | |||
| Comments: apiIssue.Comments, | |||
| HTMLURL: pr.Issue.HTMLURL(), | |||
| HasMerged: pr.HasMerged, | |||
| } | |||
| @@ -312,7 +317,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error | |||
| Before: pr.MergeBase, | |||
| After: pr.MergedCommitID, | |||
| CompareURL: setting.AppUrl + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID), | |||
| Commits: ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.FullLink()), | |||
| Commits: ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.HTMLURL()), | |||
| Repo: pr.BaseRepo.APIFormat(nil), | |||
| Pusher: pr.HeadRepo.MustOwner().APIFormat(), | |||
| Sender: doer.APIFormat(), | |||
| @@ -233,7 +233,7 @@ func (repo *Repository) FullName() string { | |||
| return repo.MustOwner().Name + "/" + repo.Name | |||
| } | |||
| func (repo *Repository) FullLink() string { | |||
| func (repo *Repository) HTMLURL() string { | |||
| return setting.AppUrl + repo.FullName() | |||
| } | |||
| @@ -248,7 +248,7 @@ func (repo *Repository) APIFormat(permission *api.Permission) *api.Repository { | |||
| Description: repo.Description, | |||
| Private: repo.IsPrivate, | |||
| Fork: repo.IsFork, | |||
| HTMLURL: repo.FullLink(), | |||
| HTMLURL: repo.HTMLURL(), | |||
| SSHURL: cloneLink.SSH, | |||
| CloneURL: cloneLink.HTTPS, | |||
| Website: repo.Website, | |||
| @@ -538,8 +538,8 @@ func ViewIssue(ctx *context.Context) { | |||
| // Get more information if it's a pull request. | |||
| if issue.IsPull { | |||
| if issue.HasMerged { | |||
| ctx.Data["DisableStatusChange"] = issue.HasMerged | |||
| if issue.PullRequest.HasMerged { | |||
| ctx.Data["DisableStatusChange"] = issue.PullRequest.HasMerged | |||
| PrepareMergedViewPullInfo(ctx, issue) | |||
| } else { | |||
| PrepareViewPullInfo(ctx, issue) | |||
| @@ -822,7 +822,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) { | |||
| // Check if issue admin/poster changes the status of issue. | |||
| if (ctx.Repo.IsWriter() || (ctx.IsSigned && issue.IsPoster(ctx.User.ID))) && | |||
| (form.Status == "reopen" || form.Status == "close") && | |||
| !(issue.IsPull && issue.HasMerged) { | |||
| !(issue.IsPull && issue.PullRequest.HasMerged) { | |||
| // Duplication and conflict check should apply to reopen pull request. | |||
| var pr *models.PullRequest | |||
| @@ -839,12 +839,12 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) { | |||
| // Regenerate patch and test conflict. | |||
| if pr == nil { | |||
| if err = issue.UpdatePatch(); err != nil { | |||
| if err = issue.PullRequest.UpdatePatch(); err != nil { | |||
| ctx.Handle(500, "UpdatePatch", err) | |||
| return | |||
| } | |||
| issue.AddToTaskQueue() | |||
| issue.PullRequest.AddToTaskQueue() | |||
| } | |||
| } | |||
| @@ -156,7 +156,7 @@ func checkPullInfo(ctx *context.Context) *models.Issue { | |||
| return nil | |||
| } | |||
| if err = issue.GetHeadRepo(); err != nil { | |||
| if err = issue.PullRequest.GetHeadRepo(); err != nil { | |||
| ctx.Handle(500, "GetHeadRepo", err) | |||
| return nil | |||
| } | |||
| @@ -172,9 +172,10 @@ func checkPullInfo(ctx *context.Context) *models.Issue { | |||
| return issue | |||
| } | |||
| func PrepareMergedViewPullInfo(ctx *context.Context, pull *models.Issue) { | |||
| func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) { | |||
| pull := issue.PullRequest | |||
| ctx.Data["HasMerged"] = true | |||
| ctx.Data["HeadTarget"] = pull.HeadUserName + "/" + pull.HeadBranch | |||
| ctx.Data["HeadTarget"] = issue.PullRequest.HeadUserName + "/" + pull.HeadBranch | |||
| ctx.Data["BaseTarget"] = ctx.Repo.Owner.Name + "/" + pull.BaseBranch | |||
| var err error | |||
| @@ -190,8 +191,9 @@ func PrepareMergedViewPullInfo(ctx *context.Context, pull *models.Issue) { | |||
| } | |||
| } | |||
| func PrepareViewPullInfo(ctx *context.Context, pull *models.Issue) *git.PullRequestInfo { | |||
| func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullRequestInfo { | |||
| repo := ctx.Repo.Repository | |||
| pull := issue.PullRequest | |||
| ctx.Data["HeadTarget"] = pull.HeadUserName + "/" + pull.HeadBranch | |||
| ctx.Data["BaseTarget"] = ctx.Repo.Owner.Name + "/" + pull.BaseBranch | |||
| @@ -245,16 +247,17 @@ func ViewPullCommits(ctx *context.Context) { | |||
| ctx.Data["PageIsPullList"] = true | |||
| ctx.Data["PageIsPullCommits"] = true | |||
| pull := checkPullInfo(ctx) | |||
| issue := checkPullInfo(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| } | |||
| pull := issue.PullRequest | |||
| ctx.Data["Username"] = pull.HeadUserName | |||
| ctx.Data["Reponame"] = pull.HeadRepo.Name | |||
| var commits *list.List | |||
| if pull.HasMerged { | |||
| PrepareMergedViewPullInfo(ctx, pull) | |||
| PrepareMergedViewPullInfo(ctx, issue) | |||
| if ctx.Written() { | |||
| return | |||
| } | |||
| @@ -275,7 +278,7 @@ func ViewPullCommits(ctx *context.Context) { | |||
| } | |||
| } else { | |||
| prInfo := PrepareViewPullInfo(ctx, pull) | |||
| prInfo := PrepareViewPullInfo(ctx, issue) | |||
| if ctx.Written() { | |||
| return | |||
| } else if prInfo == nil { | |||
| @@ -296,10 +299,11 @@ func ViewPullFiles(ctx *context.Context) { | |||
| ctx.Data["PageIsPullList"] = true | |||
| ctx.Data["PageIsPullFiles"] = true | |||
| pull := checkPullInfo(ctx) | |||
| issue := checkPullInfo(ctx) | |||
| if ctx.Written() { | |||
| return | |||
| } | |||
| pull := issue.PullRequest | |||
| var ( | |||
| diffRepoPath string | |||
| @@ -309,7 +313,7 @@ func ViewPullFiles(ctx *context.Context) { | |||
| ) | |||
| if pull.HasMerged { | |||
| PrepareMergedViewPullInfo(ctx, pull) | |||
| PrepareMergedViewPullInfo(ctx, issue) | |||
| if ctx.Written() { | |||
| return | |||
| } | |||
| @@ -319,7 +323,7 @@ func ViewPullFiles(ctx *context.Context) { | |||
| endCommitID = pull.MergedCommitID | |||
| gitRepo = ctx.Repo.GitRepo | |||
| } else { | |||
| prInfo := PrepareViewPullInfo(ctx, pull) | |||
| prInfo := PrepareViewPullInfo(ctx, issue) | |||
| if ctx.Written() { | |||
| return | |||
| } else if prInfo == nil { | |||
| @@ -368,7 +368,7 @@ func TestWebhook(ctx *context.Context) { | |||
| { | |||
| ID: commit.ID.String(), | |||
| Message: commit.Message(), | |||
| URL: ctx.Repo.Repository.FullLink() + "/commit/" + commit.ID.String(), | |||
| URL: ctx.Repo.Repository.HTMLURL() + "/commit/" + commit.ID.String(), | |||
| Author: &api.PayloadUser{ | |||
| Name: commit.Author.Name, | |||
| Email: commit.Author.Email, | |||
| @@ -1 +1 @@ | |||
| 0.9.81.0816 | |||
| 0.9.82.0816 | |||
| @@ -151,15 +151,15 @@ | |||
| {{if .Issue.IsPull}} | |||
| <div class="comment merge box"> | |||
| <a class="avatar text | |||
| {{if .Issue.HasMerged}}purple | |||
| {{if .Issue.PullRequest.HasMerged}}purple | |||
| {{else if .Issue.IsClosed}}grey | |||
| {{else if .IsPullReuqestBroken}}red | |||
| {{else if .Issue.IsChecking}}yellow | |||
| {{else if .Issue.CanAutoMerge}}green | |||
| {{else if .Issue.PullRequest.IsChecking}}yellow | |||
| {{else if .Issue.PullRequest.CanAutoMerge}}green | |||
| {{else}}red{{end}}"><span class="mega-octicon octicon-git-merge"></span></a> | |||
| <div class="content"> | |||
| <div class="ui merge segment"> | |||
| {{if .Issue.HasMerged}} | |||
| {{if .Issue.PullRequest.HasMerged}} | |||
| <div class="item text purple"> | |||
| {{$.i18n.Tr "repo.pulls.has_merged"}} | |||
| </div> | |||
| @@ -172,12 +172,12 @@ | |||
| <span class="octicon octicon-x"></span> | |||
| {{$.i18n.Tr "repo.pulls.data_broken"}} | |||
| </div> | |||
| {{else if .Issue.IsChecking}} | |||
| {{else if .Issue.PullRequest.IsChecking}} | |||
| <div class="item text yellow"> | |||
| <span class="octicon octicon-sync"></span> | |||
| {{$.i18n.Tr "repo.pulls.is_checking"}} | |||
| </div> | |||
| {{else if .Issue.CanAutoMerge}} | |||
| {{else if .Issue.PullRequest.CanAutoMerge}} | |||
| <div class="item text green"> | |||
| <span class="octicon octicon-check"></span> | |||
| {{$.i18n.Tr "repo.pulls.can_auto_merge_desc"}} | |||
| @@ -25,9 +25,9 @@ | |||
| {{end}} | |||
| {{if .Issue.IsPull}} | |||
| {{if .Issue.HasMerged}} | |||
| {{ $mergedStr:= TimeSince .Issue.Merged $.Lang }} | |||
| <a {{if gt .Issue.Merger.ID 0}}href="{{.Issue.Merger.HomeLink}}"{{end}}>{{.Issue.Merger.Name}}</a> | |||
| {{if .Issue.PullRequest.HasMerged}} | |||
| {{ $mergedStr:= TimeSince .Issue.PullRequest.Merged $.Lang }} | |||
| <a {{if gt .Issue.PullRequest.Merger.ID 0}}href="{{.Issue.PullRequest.Merger.HomeLink}}"{{end}}>{{.Issue.PullRequest.Merger.Name}}</a> | |||
| <span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Safe}}</span> | |||
| {{else}} | |||
| <a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.Name}}</a> | |||