Skip to content

Commit

Permalink
Adds functionality to change target branch of created pull requests
Browse files Browse the repository at this point in the history
Signed-off-by: Mario Lubenka <mario.lubenka@googlemail.com>
  • Loading branch information
saitho committed Apr 2, 2019
1 parent bf5af87 commit f985e67
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 18 deletions.
19 changes: 19 additions & 0 deletions models/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ const (
CommentTypeLock
// Unlocks a previously locked issue
CommentTypeUnlock
// Change pull request's target branch
CommentTypeChangeTargetBranch
)

// CommentTag defines comment tag type
Expand Down Expand Up @@ -116,6 +118,8 @@ type Comment struct {
Assignee *User `xorm:"-"`
OldTitle string
NewTitle string
OldBranch string
NewBranch string
DependentIssueID int64
DependentIssue *Issue `xorm:"-"`

Expand Down Expand Up @@ -525,6 +529,8 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
Content: opts.Content,
OldTitle: opts.OldTitle,
NewTitle: opts.NewTitle,
OldBranch: opts.OldBranch,
NewBranch: opts.NewBranch,
DependentIssueID: opts.DependentIssueID,
TreePath: opts.TreePath,
ReviewID: opts.ReviewID,
Expand Down Expand Up @@ -737,6 +743,17 @@ func createChangeTitleComment(e *xorm.Session, doer *User, repo *Repository, iss
})
}

func createChangePullRequestTargetBranchComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, oldBranch string, newBranch string) (*Comment, error) {
return createComment(e, &CreateCommentOptions{
Type: CommentTypeChangeTargetBranch,
Doer: doer,
Repo: repo,
Issue: issue,
OldBranch: oldBranch,
NewBranch: newBranch,
})
}

func createDeleteBranchComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, branchName string) (*Comment, error) {
return createComment(e, &CreateCommentOptions{
Type: CommentTypeDeleteBranch,
Expand Down Expand Up @@ -798,6 +815,8 @@ type CreateCommentOptions struct {
RemovedAssignee bool
OldTitle string
NewTitle string
OldBranch string
NewBranch string
CommitID int64
CommitSHA string
Patch string
Expand Down
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ var migrations = []Migration{
NewMigration("hot fix for wrong release sha1 on release table", fixReleaseSha1OnReleaseTable),
// v83 -> v84
NewMigration("add uploader id for table attachment", addUploaderIDForAttachment),
// v84 -> v85
NewMigration("new feature: change target branch of pull requests", featureChangeTargetBranch),
}

// Migrate database to current version
Expand Down
22 changes: 22 additions & 0 deletions models/migrations/v84.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
"fmt"
"github.com/go-xorm/xorm"
)

func featureChangeTargetBranch(x *xorm.Engine) error {
type Comment struct {
OldBranch string
NewBranch string
}

if err := x.Sync2(new(Comment)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}
return nil
}
44 changes: 44 additions & 0 deletions models/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -1410,6 +1410,50 @@ func ChangeUsernameInPullRequests(oldUserName, newUserName string) error {
return err
}

// ChangeTargetBranch changes the target branch of this pull request, as the given user.
func (pr *PullRequest) ChangeTargetBranch(doer *User, targetBranch string) (err error) {
oldBranch := pr.BaseBranch
if oldBranch == targetBranch {
return nil
}
pr.BaseBranch = targetBranch
sess := x.NewSession()
defer sess.Close()

if err = sess.Begin(); err != nil {
return err
}

if _, err := sess.ID(pr.ID).Cols("base_branch").Update(pr); err != nil {
return fmt.Errorf("update pull request: %v", err)
}

issue := pr.Issue

if _, err = createChangePullRequestTargetBranchComment(sess, doer, issue.Repo, issue, oldBranch, targetBranch); err != nil {
return fmt.Errorf("createChangePullRequestTargetBranchComment: %v", err)
}

if err = sess.Commit(); err != nil {
return err
}

mode, _ := AccessLevel(issue.Poster, issue.Repo)
err = PrepareWebhooks(issue.Repo, HookEventPullRequest, &api.PullRequestPayload{
Action: api.HookIssueEdited,
Index: issue.Index,
PullRequest: pr.APIFormat(),
Repository: issue.Repo.APIFormat(mode),
Sender: doer.APIFormat(),
})
if err != nil {
log.Error("PrepareWebhooks [is_pull: true]: %v", err)
} else {
go HookQueue.Add(issue.RepoID)
}
return nil
}

// checkAndUpdateStatus checks if pull request is possible to leaving checking status,
// and set to be either conflict or mergeable.
func (pr *PullRequest) checkAndUpdateStatus() {
Expand Down
3 changes: 2 additions & 1 deletion options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -920,8 +920,9 @@ pulls.no_results = No results found.
pulls.nothing_to_compare = These branches are equal. There is no need to create a pull request.
pulls.has_pull_request = `A pull request between these branches already exists: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create = Create Pull Request
pulls.title_desc = wants to merge %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code>
pulls.title_desc = wants to merge %[1]d commits from <code>%[2]s</code> into <code id="branch_target">%[3]s</code>
pulls.merged_title_desc = merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s
pulls.change_target_branch_at = `changed target branch from <b>%s</b> to <b>%s</b> %s`
pulls.tab_conversation = Conversation
pulls.tab_commits = Commits
pulls.tab_files = Files Changed
Expand Down
60 changes: 47 additions & 13 deletions public/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -786,28 +786,62 @@ function initRepository() {
$issueTitle.toggle();
$('.not-in-edit').toggle();
$('#edit-title-input').toggle();
$('#pull-desc').toggle();
$('#pull-desc-edit').toggle();
$('.in-edit').toggle();
$editInput.focus();
return false;
};

var changeBranchSelect = function () {
var selectionTextField = $('#pull-target-branch');

var baseName = selectionTextField.data('basename');
var branchNameNew = $(this).data('branch');
var branchNameOld = selectionTextField.data('branch');

// Replace branch name to keep translation from HTML template
selectionTextField.html(selectionTextField.html().replace(baseName + ':' + branchNameOld, baseName + ':' + branchNameNew));
selectionTextField.data('branch', branchNameNew); // update branch name in setting
};
$('#branch-select > .item').click(changeBranchSelect);

$('#edit-title').click(editTitleToggle);
$('#cancel-edit-title').click(editTitleToggle);
$('#save-edit-title').click(editTitleToggle).click(function () {
if ($editInput.val().length == 0 ||
$editInput.val() == $issueTitle.text()) {

var pullrequest_targetbranch_change = function(update_url) {
var target_branch = $('#pull-target-branch').data('branch');
if (target_branch === $('#branch_target').text()) {
$editInput.val($issueTitle.text());
return false;
}
$.post(update_url, {
"_csrf": csrf,
"target_branch": target_branch
},
function (data) {
$('#branch_target').text(data.base_branch);
reload();
});
};

var pullrequest_target_update_url = $(this).data('target-update-url');
if ($editInput.val().length === 0 ||
$editInput.val() === $issueTitle.text()) {
$editInput.val($issueTitle.text());
return false;
pullrequest_targetbranch_change(pullrequest_target_update_url);
} else {
$.post($(this).data('update-url'), {
"_csrf": csrf,
"title": $editInput.val()
},
function (data) {
$editInput.val(data.title);
$issueTitle.text(data.title);
pullrequest_targetbranch_change(pullrequest_target_update_url);
});
}

$.post($(this).data('update-url'), {
"_csrf": csrf,
"title": $editInput.val()
},
function (data) {
$editInput.val(data.title);
$issueTitle.text(data.title);
reload();
});
return false;
});

Expand Down
23 changes: 23 additions & 0 deletions routers/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,28 @@ func commentTag(repo *models.Repository, poster *models.User, issue *models.Issu
return models.CommentTagNone, nil
}

func getBranchData(ctx *context.Context, issue *models.Issue) {
ctx.Data["BaseBranch"] = nil
ctx.Data["HeadBranch"] = nil
ctx.Data["HeadUserName"] = nil
ctx.Data["BaseName"] = ctx.Repo.Repository.OwnerName
if issue.IsPull {
pull := issue.PullRequest
ctx.Data["BaseBranch"] = pull.BaseBranch
ctx.Data["HeadBranch"] = pull.HeadBranch
ctx.Data["HeadUserName"] = pull.HeadUserName

headUser, err := models.GetUserByName(pull.HeadUserName)
if headUser.ID == ctx.Repo.Owner.ID {
ctx.Data["BaseName"] = headUser.Name
}
if err != nil {
ctx.ServerError("getBranchData", err)
return
}
}
}

// ViewIssue render issue view page
func ViewIssue(ctx *context.Context) {
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
Expand Down Expand Up @@ -848,6 +870,7 @@ func ViewIssue(ctx *context.Context) {
}
}

getBranchData(ctx, issue)
if issue.IsPull {
pull := issue.PullRequest
pull.Issue = issue
Expand Down
34 changes: 34 additions & 0 deletions routers/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ func ViewPullCommits(ctx *context.Context) {
ctx.Data["Commits"] = commits
ctx.Data["CommitCount"] = commits.Len()

getBranchData(ctx, issue)
ctx.HTML(200, tplPullCommits)
}

Expand Down Expand Up @@ -519,6 +520,7 @@ func ViewPullFiles(ctx *context.Context) {
ctx.ServerError("GetCurrentReview", err)
return
}
getBranchData(ctx, issue)
ctx.HTML(200, tplPullFiles)
}

Expand Down Expand Up @@ -1184,3 +1186,35 @@ func DownloadPullPatch(ctx *context.Context) {
return
}
}

// UpdatePullRequestTarget change pull request's target branch
func UpdatePullRequestTarget(ctx *context.Context) {
issue := GetActionIssue(ctx)
pr := issue.PullRequest
if !issue.IsPull {
return
}
if ctx.Written() {
return
}

if !ctx.IsSigned || (!issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
ctx.Error(403)
return
}

targetBranch := ctx.QueryTrim("target_branch")
if len(targetBranch) == 0 {
ctx.Error(204)
return
}

if err := pr.ChangeTargetBranch(ctx.User, targetBranch); err != nil {
ctx.ServerError("UpdatePullRequestTarget", err)
return
}

ctx.JSON(200, map[string]interface{}{
"base_branch": pr.BaseBranch,
})
}
5 changes: 5 additions & 0 deletions routers/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,11 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/compare/*", context.RepoMustNotBeArchived(), reqRepoCodeReader, reqRepoPullsReader, repo.MustAllowPulls, repo.SetEditorconfigIfExists).
Get(repo.SetDiffViewStyle, repo.CompareAndPullRequest).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
m.Group("/pull", func() {
m.Group("/:index", func() {
m.Post("/target_branch", repo.UpdatePullRequestTarget)
}, context.RepoMustNotBeArchived())
}, context.RepoMustNotBeArchived())

m.Group("", func() {
m.Group("", func() {
Expand Down
12 changes: 11 additions & 1 deletion templates/repo/issue/view_content/comments.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
5 = COMMENT_REF, 6 = PULL_REF, 7 = COMMENT_LABEL, 12 = START_TRACKING,
13 = STOP_TRACKING, 14 = ADD_TIME_MANUAL, 16 = ADDED_DEADLINE, 17 = MODIFIED_DEADLINE,
18 = REMOVED_DEADLINE, 19 = ADD_DEPENDENCY, 20 = REMOVE_DEPENDENCY, 21 = CODE,
22 = REVIEW, 23 = ISSUE_LOCKED, 24 = ISSUE_UNLOCKED -->
22 = REVIEW, 23 = ISSUE_LOCKED, 24 = ISSUE_UNLOCKED, 25 = TARGET_BRANCH_CHANGED -->
{{if eq .Type 0}}
<div class="comment" id="{{.HashTag}}">
<a class="avatar" {{if gt .Poster.ID 0}}href="{{.Poster.HomeLink}}"{{end}}>
Expand Down Expand Up @@ -389,5 +389,15 @@
{{$.i18n.Tr "repo.issues.unlock_comment" $createdStr | Safe}}
</span>
</div>
{{else if eq .Type 25}}
<div class="event">
<span class="octicon octicon-primitive-dot"></span>
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
<img src="{{.Poster.RelAvatarLink}}">
</a>
<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a>
{{$.i18n.Tr "repo.pulls.change_target_branch_at" (.OldBranch|Escape) (.NewBranch|Escape) $createdStr | Safe}}
</span>
</div>
{{end}}
{{end}}
34 changes: 31 additions & 3 deletions templates/repo/issue/view_title.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<div class="edit-zone text right">
<div id="edit-title" class="ui basic green not-in-edit button">{{.i18n.Tr "repo.issues.edit"}}</div>
<div id="cancel-edit-title" class="ui basic blue in-edit button" style="display: none">{{.i18n.Tr "repo.issues.cancel"}}</div>
<div id="save-edit-title" class="ui green in-edit button" style="display: none" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title">{{.i18n.Tr "repo.issues.save"}}</div>
<div id="save-edit-title" class="ui green in-edit button" style="display: none" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title" {{if .Issue.IsPull}}data-target-update-url="{{$.RepoLink}}/pull/{{.Issue.Index}}/target_branch"{{end}}>{{.i18n.Tr "repo.issues.save"}}</div>
</div>
</div>
{{end}}
Expand All @@ -30,8 +30,36 @@
<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 | Str2html}}</span>
{{else}}
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.Name}}</a>
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
<span id="pull-desc" class="pull-desc"><a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.Name}}</a> {{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
<span id="pull-desc-edit" style="display: none">
<div class="ui floating filter dropdown" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}">
<div class="ui basic small button">
<span class="text" id="pull-target-branch" data-basename="{{$.BaseName}}" data-branch="{{$.BaseBranch}}">{{.i18n.Tr "repo.pulls.compare_base"}}: {{$.BaseName}}:{{$.BaseBranch}}</span>
<i class="dropdown icon"></i>
</div>
<div class="menu">
<div class="ui icon search input">
<i class="filter icon"></i>
<input name="search" placeholder="{{.i18n.Tr "repo.pulls.filter_branch"}}...">
</div>
<div class="scrolling menu" id="branch-select">
{{range .Branches}}
{{ $sameBase := ne $.BaseName $.HeadUserName }}
{{ $differentBranch := ne . $.HeadBranch }}
{{ if or $sameBase $differentBranch }}
<div class="item {{if eq $.BaseBranch .}}selected{{end}}" data-branch="{{.}}">{{$.BaseName}}{{if $.HeadRepo}}/{{$.HeadRepo}}{{end}}:{{.}}</div>
{{ end }}
{{end}}
</div>
</div>
</div>
...
<div class="ui floating filter dropdown">
<div class="ui basic small button">
<span class="text">{{.i18n.Tr "repo.pulls.compare_compare"}}: {{$.HeadTarget}}</span>
</div>
</div>
</span>
{{end}}
{{else}}
{{ $createdStr:= TimeSinceUnix .Issue.CreatedUnix $.Lang }}
Expand Down

0 comments on commit f985e67

Please sign in to comment.