- Fill Milestone and Assignee field when available in webhook payloadtags/v0.9.99
github.com/gogits/chardet = commit:2404f77 | github.com/gogits/chardet = commit:2404f77 | ||||
github.com/gogits/cron = commit:7f3990a | github.com/gogits/cron = commit:7f3990a | ||||
github.com/gogits/git-module = commit:f78bf3b | 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/issue9/identicon = commit:d36b545 | ||||
github.com/jaytaylor/html2text = commit:52d9b78 | github.com/jaytaylor/html2text = commit:52d9b78 | ||||
github.com/kardianos/minwinsvc = commit:cad6b2b | github.com/kardianos/minwinsvc = commit:cad6b2b |
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) | ![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) | ||||
##### 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 | | | Web | UI | Preview | | ||||
|:-------------:|:-------:|:-------:| | |:-------------:|:-------:|:-------:| |
{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"}, | {"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"}, | ||||
{"gopkg.in/ini.v1", ini.Version, "1.8.4"}, | {"gopkg.in/ini.v1", ini.Version, "1.8.4"}, | ||||
{"gopkg.in/macaron.v1", macaron.Version, "1.1.7"}, | {"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 { | for _, c := range checkers { | ||||
if !version.Compare(c.Version(), c.Expected, ">=") { | if !version.Compare(c.Version(), c.Expected, ">=") { |
- name: github.com/gogits/git-module | - name: github.com/gogits/git-module | ||||
version: f78bf3bf703cb3eb0e85a9475d26826939feda4f | version: f78bf3bf703cb3eb0e85a9475d26826939feda4f | ||||
- name: github.com/gogits/go-gogs-client | - name: github.com/gogits/go-gogs-client | ||||
version: e363d3ff8f70d0fe813324eedf228684af41c29c | |||||
version: 51c4df8c350b32f095c8eb236aae2e306025eead | |||||
- name: github.com/issue9/identicon | - name: github.com/issue9/identicon | ||||
version: d36b54562f4cf70c83653e13dc95c220c79ef521 | version: d36b54562f4cf70c83653e13dc95c220c79ef521 | ||||
- name: github.com/jaytaylor/html2text | - name: github.com/jaytaylor/html2text |
"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
) | ) | ||||
const APP_VER = "0.9.81.0816" | |||||
const APP_VER = "0.9.82.0816" | |||||
func init() { | func init() { | ||||
runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) |
Before: oldCommitID, | Before: oldCommitID, | ||||
After: newCommitID, | After: newCommitID, | ||||
CompareURL: setting.AppUrl + commit.CompareURL, | CompareURL: setting.AppUrl + commit.CompareURL, | ||||
Commits: commit.ToApiPayloadCommits(repo.FullLink()), | |||||
Commits: commit.ToApiPayloadCommits(repo.HTMLURL()), | |||||
Repo: apiRepo, | Repo: apiRepo, | ||||
Pusher: apiPusher, | Pusher: apiPusher, | ||||
Sender: apiPusher, | Sender: apiPusher, |
type Issue struct { | type Issue struct { | ||||
ID int64 `xorm:"pk autoincr"` | ID int64 `xorm:"pk autoincr"` | ||||
RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"` | RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"` | ||||
Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository. | |||||
Title string `xorm:"name"` | |||||
Repo *Repository `xorm:"-"` | Repo *Repository `xorm:"-"` | ||||
Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository. | |||||
PosterID int64 | PosterID int64 | ||||
Poster *User `xorm:"-"` | Poster *User `xorm:"-"` | ||||
Title string `xorm:"name"` | |||||
Content string `xorm:"TEXT"` | |||||
RenderedContent string `xorm:"-"` | |||||
Labels []*Label `xorm:"-"` | Labels []*Label `xorm:"-"` | ||||
MilestoneID int64 | MilestoneID int64 | ||||
Milestone *Milestone `xorm:"-"` | Milestone *Milestone `xorm:"-"` | ||||
Priority int | |||||
AssigneeID int64 | AssigneeID int64 | ||||
Assignee *User `xorm:"-"` | Assignee *User `xorm:"-"` | ||||
IsRead bool `xorm:"-"` | |||||
IsPull bool // Indicates whether is a pull request or not. | |||||
*PullRequest `xorm:"-"` | |||||
IsClosed bool | 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 | NumComments int | ||||
Deadline time.Time `xorm:"-"` | Deadline time.Time `xorm:"-"` | ||||
return issue.loadAttributes(x) | 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. | // State returns string representation of issue status. | ||||
func (i *Issue) State() api.StateType { | func (i *Issue) State() api.StateType { | ||||
if i.IsClosed { | if i.IsClosed { | ||||
apiIssue := &api.Issue{ | apiIssue := &api.Issue{ | ||||
ID: issue.ID, | ID: issue.ID, | ||||
Index: issue.Index, | Index: issue.Index, | ||||
State: issue.State(), | |||||
Poster: issue.Poster.APIFormat(), | |||||
Title: issue.Title, | Title: issue.Title, | ||||
Body: issue.Content, | Body: issue.Content, | ||||
User: issue.Poster.APIFormat(), | |||||
Labels: apiLabels, | Labels: apiLabels, | ||||
State: issue.State(), | |||||
Comments: issue.NumComments, | Comments: issue.NumComments, | ||||
Created: issue.Created, | Created: issue.Created, | ||||
Updated: issue.Updated, | Updated: issue.Updated, | ||||
return "issue-" + com.ToStr(i.ID) | 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. | // IsPoster returns true if given user by ID is the poster. | ||||
func (i *Issue) IsPoster(uid int64) bool { | func (i *Issue) IsPoster(uid int64) bool { | ||||
return i.PosterID == uid | return i.PosterID == uid | ||||
opts.Issue.Title = strings.TrimSpace(opts.Issue.Title) | opts.Issue.Title = strings.TrimSpace(opts.Issue.Title) | ||||
opts.Issue.Index = opts.Repo.NextIssueIndex() | 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 { | 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 { | if _, err = e.Insert(opts.Issue); err != nil { | ||||
return err | return err | ||||
} | } | ||||
} | } | ||||
} | } | ||||
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 { | if err = newIssueUsers(e, opts.Repo, opts.Issue); err != nil { | ||||
return err | return err | ||||
} | } |
data := map[string]interface{}{ | data := map[string]interface{}{ | ||||
"Subject": subject, | "Subject": subject, | ||||
"RepoName": repoName, | "RepoName": repoName, | ||||
"Link": repo.FullLink(), | |||||
"Link": repo.HTMLURL(), | |||||
} | } | ||||
body, err := mailRender.HTMLString(string(MAIL_NOTIFY_COLLABORATOR), data) | body, err := mailRender.HTMLString(string(MAIL_NOTIFY_COLLABORATOR), data) | ||||
if err != nil { | if err != nil { | ||||
func composeIssueMessage(issue *Issue, doer *User, tplName base.TplName, tos []string, info string) *mailer.Message { | func composeIssueMessage(issue *Issue, doer *User, tplName base.TplName, tos []string, info string) *mailer.Message { | ||||
subject := issue.MailSubject() | 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 | data["Doer"] = doer | ||||
content, err := mailRender.HTMLString(string(tplName), data) | content, err := mailRender.HTMLString(string(tplName), data) | ||||
if err != nil { | if err != nil { |
} | } | ||||
func (pr *PullRequest) LoadIssue() (err error) { | func (pr *PullRequest) LoadIssue() (err error) { | ||||
if pr.Issue != nil { | |||||
return nil | |||||
} | |||||
pr.Issue, err = GetIssueByID(pr.IssueID) | pr.Issue, err = GetIssueByID(pr.IssueID) | ||||
return err | return err | ||||
} | } | ||||
apiPullRequest := &api.PullRequest{ | apiPullRequest := &api.PullRequest{ | ||||
ID: pr.ID, | ID: pr.ID, | ||||
Index: pr.Index, | Index: pr.Index, | ||||
State: apiIssue.State, | |||||
Poster: apiIssue.Poster, | |||||
Title: apiIssue.Title, | Title: apiIssue.Title, | ||||
Body: apiIssue.Body, | Body: apiIssue.Body, | ||||
User: apiIssue.User, | |||||
Labels: apiIssue.Labels, | Labels: apiIssue.Labels, | ||||
Milestone: apiIssue.Milestone, | Milestone: apiIssue.Milestone, | ||||
Assignee: apiIssue.Assignee, | Assignee: apiIssue.Assignee, | ||||
State: apiIssue.State, | |||||
Comments: apiIssue.Comments, | Comments: apiIssue.Comments, | ||||
HTMLURL: pr.Issue.HTMLURL(), | |||||
HasMerged: pr.HasMerged, | HasMerged: pr.HasMerged, | ||||
} | } | ||||
Before: pr.MergeBase, | Before: pr.MergeBase, | ||||
After: pr.MergedCommitID, | After: pr.MergedCommitID, | ||||
CompareURL: setting.AppUrl + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, 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), | Repo: pr.BaseRepo.APIFormat(nil), | ||||
Pusher: pr.HeadRepo.MustOwner().APIFormat(), | Pusher: pr.HeadRepo.MustOwner().APIFormat(), | ||||
Sender: doer.APIFormat(), | Sender: doer.APIFormat(), |
return repo.MustOwner().Name + "/" + repo.Name | return repo.MustOwner().Name + "/" + repo.Name | ||||
} | } | ||||
func (repo *Repository) FullLink() string { | |||||
func (repo *Repository) HTMLURL() string { | |||||
return setting.AppUrl + repo.FullName() | return setting.AppUrl + repo.FullName() | ||||
} | } | ||||
Description: repo.Description, | Description: repo.Description, | ||||
Private: repo.IsPrivate, | Private: repo.IsPrivate, | ||||
Fork: repo.IsFork, | Fork: repo.IsFork, | ||||
HTMLURL: repo.FullLink(), | |||||
HTMLURL: repo.HTMLURL(), | |||||
SSHURL: cloneLink.SSH, | SSHURL: cloneLink.SSH, | ||||
CloneURL: cloneLink.HTTPS, | CloneURL: cloneLink.HTTPS, | ||||
Website: repo.Website, | Website: repo.Website, |
// Get more information if it's a pull request. | // Get more information if it's a pull request. | ||||
if issue.IsPull { | if issue.IsPull { | ||||
if issue.HasMerged { | |||||
ctx.Data["DisableStatusChange"] = issue.HasMerged | |||||
if issue.PullRequest.HasMerged { | |||||
ctx.Data["DisableStatusChange"] = issue.PullRequest.HasMerged | |||||
PrepareMergedViewPullInfo(ctx, issue) | PrepareMergedViewPullInfo(ctx, issue) | ||||
} else { | } else { | ||||
PrepareViewPullInfo(ctx, issue) | PrepareViewPullInfo(ctx, issue) | ||||
// Check if issue admin/poster changes the status of issue. | // Check if issue admin/poster changes the status of issue. | ||||
if (ctx.Repo.IsWriter() || (ctx.IsSigned && issue.IsPoster(ctx.User.ID))) && | if (ctx.Repo.IsWriter() || (ctx.IsSigned && issue.IsPoster(ctx.User.ID))) && | ||||
(form.Status == "reopen" || form.Status == "close") && | (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. | // Duplication and conflict check should apply to reopen pull request. | ||||
var pr *models.PullRequest | var pr *models.PullRequest | ||||
// Regenerate patch and test conflict. | // Regenerate patch and test conflict. | ||||
if pr == nil { | if pr == nil { | ||||
if err = issue.UpdatePatch(); err != nil { | |||||
if err = issue.PullRequest.UpdatePatch(); err != nil { | |||||
ctx.Handle(500, "UpdatePatch", err) | ctx.Handle(500, "UpdatePatch", err) | ||||
return | return | ||||
} | } | ||||
issue.AddToTaskQueue() | |||||
issue.PullRequest.AddToTaskQueue() | |||||
} | } | ||||
} | } | ||||
return nil | return nil | ||||
} | } | ||||
if err = issue.GetHeadRepo(); err != nil { | |||||
if err = issue.PullRequest.GetHeadRepo(); err != nil { | |||||
ctx.Handle(500, "GetHeadRepo", err) | ctx.Handle(500, "GetHeadRepo", err) | ||||
return nil | return nil | ||||
} | } | ||||
return 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["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 | ctx.Data["BaseTarget"] = ctx.Repo.Owner.Name + "/" + pull.BaseBranch | ||||
var err error | var err error | ||||
} | } | ||||
} | } | ||||
func PrepareViewPullInfo(ctx *context.Context, pull *models.Issue) *git.PullRequestInfo { | |||||
func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullRequestInfo { | |||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
pull := issue.PullRequest | |||||
ctx.Data["HeadTarget"] = pull.HeadUserName + "/" + pull.HeadBranch | ctx.Data["HeadTarget"] = pull.HeadUserName + "/" + pull.HeadBranch | ||||
ctx.Data["BaseTarget"] = ctx.Repo.Owner.Name + "/" + pull.BaseBranch | ctx.Data["BaseTarget"] = ctx.Repo.Owner.Name + "/" + pull.BaseBranch | ||||
ctx.Data["PageIsPullList"] = true | ctx.Data["PageIsPullList"] = true | ||||
ctx.Data["PageIsPullCommits"] = true | ctx.Data["PageIsPullCommits"] = true | ||||
pull := checkPullInfo(ctx) | |||||
issue := checkPullInfo(ctx) | |||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
pull := issue.PullRequest | |||||
ctx.Data["Username"] = pull.HeadUserName | ctx.Data["Username"] = pull.HeadUserName | ||||
ctx.Data["Reponame"] = pull.HeadRepo.Name | ctx.Data["Reponame"] = pull.HeadRepo.Name | ||||
var commits *list.List | var commits *list.List | ||||
if pull.HasMerged { | if pull.HasMerged { | ||||
PrepareMergedViewPullInfo(ctx, pull) | |||||
PrepareMergedViewPullInfo(ctx, issue) | |||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
prInfo := PrepareViewPullInfo(ctx, pull) | |||||
prInfo := PrepareViewPullInfo(ctx, issue) | |||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} else if prInfo == nil { | } else if prInfo == nil { | ||||
ctx.Data["PageIsPullList"] = true | ctx.Data["PageIsPullList"] = true | ||||
ctx.Data["PageIsPullFiles"] = true | ctx.Data["PageIsPullFiles"] = true | ||||
pull := checkPullInfo(ctx) | |||||
issue := checkPullInfo(ctx) | |||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
pull := issue.PullRequest | |||||
var ( | var ( | ||||
diffRepoPath string | diffRepoPath string | ||||
) | ) | ||||
if pull.HasMerged { | if pull.HasMerged { | ||||
PrepareMergedViewPullInfo(ctx, pull) | |||||
PrepareMergedViewPullInfo(ctx, issue) | |||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} | } | ||||
endCommitID = pull.MergedCommitID | endCommitID = pull.MergedCommitID | ||||
gitRepo = ctx.Repo.GitRepo | gitRepo = ctx.Repo.GitRepo | ||||
} else { | } else { | ||||
prInfo := PrepareViewPullInfo(ctx, pull) | |||||
prInfo := PrepareViewPullInfo(ctx, issue) | |||||
if ctx.Written() { | if ctx.Written() { | ||||
return | return | ||||
} else if prInfo == nil { | } else if prInfo == nil { |
{ | { | ||||
ID: commit.ID.String(), | ID: commit.ID.String(), | ||||
Message: commit.Message(), | Message: commit.Message(), | ||||
URL: ctx.Repo.Repository.FullLink() + "/commit/" + commit.ID.String(), | |||||
URL: ctx.Repo.Repository.HTMLURL() + "/commit/" + commit.ID.String(), | |||||
Author: &api.PayloadUser{ | Author: &api.PayloadUser{ | ||||
Name: commit.Author.Name, | Name: commit.Author.Name, | ||||
Email: commit.Author.Email, | Email: commit.Author.Email, |
0.9.81.0816 | |||||
0.9.82.0816 |
{{if .Issue.IsPull}} | {{if .Issue.IsPull}} | ||||
<div class="comment merge box"> | <div class="comment merge box"> | ||||
<a class="avatar text | <a class="avatar text | ||||
{{if .Issue.HasMerged}}purple | |||||
{{if .Issue.PullRequest.HasMerged}}purple | |||||
{{else if .Issue.IsClosed}}grey | {{else if .Issue.IsClosed}}grey | ||||
{{else if .IsPullReuqestBroken}}red | {{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> | {{else}}red{{end}}"><span class="mega-octicon octicon-git-merge"></span></a> | ||||
<div class="content"> | <div class="content"> | ||||
<div class="ui merge segment"> | <div class="ui merge segment"> | ||||
{{if .Issue.HasMerged}} | |||||
{{if .Issue.PullRequest.HasMerged}} | |||||
<div class="item text purple"> | <div class="item text purple"> | ||||
{{$.i18n.Tr "repo.pulls.has_merged"}} | {{$.i18n.Tr "repo.pulls.has_merged"}} | ||||
</div> | </div> | ||||
<span class="octicon octicon-x"></span> | <span class="octicon octicon-x"></span> | ||||
{{$.i18n.Tr "repo.pulls.data_broken"}} | {{$.i18n.Tr "repo.pulls.data_broken"}} | ||||
</div> | </div> | ||||
{{else if .Issue.IsChecking}} | |||||
{{else if .Issue.PullRequest.IsChecking}} | |||||
<div class="item text yellow"> | <div class="item text yellow"> | ||||
<span class="octicon octicon-sync"></span> | <span class="octicon octicon-sync"></span> | ||||
{{$.i18n.Tr "repo.pulls.is_checking"}} | {{$.i18n.Tr "repo.pulls.is_checking"}} | ||||
</div> | </div> | ||||
{{else if .Issue.CanAutoMerge}} | |||||
{{else if .Issue.PullRequest.CanAutoMerge}} | |||||
<div class="item text green"> | <div class="item text green"> | ||||
<span class="octicon octicon-check"></span> | <span class="octicon octicon-check"></span> | ||||
{{$.i18n.Tr "repo.pulls.can_auto_merge_desc"}} | {{$.i18n.Tr "repo.pulls.can_auto_merge_desc"}} |
{{end}} | {{end}} | ||||
{{if .Issue.IsPull}} | {{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> | <span class="pull-desc">{{$.i18n.Tr "repo.pulls.merged_title_desc" .NumCommits .HeadTarget .BaseTarget $mergedStr | Safe}}</span> | ||||
{{else}} | {{else}} | ||||
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.Name}}</a> | <a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.Name}}</a> |