Skip to content

Change target branch for pull request #6488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
Dec 16, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f985e67
Adds functionality to change target branch of created pull requests
saitho Mar 27, 2019
1c01294
Merge remote-tracking branch 'origin/master' into feature/choose_pull…
saitho Apr 20, 2019
a520c5e
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Aug 13, 2019
6c48735
Use const instead of var in JavaScript additions
saitho Aug 13, 2019
be71ada
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Sep 17, 2019
411f54e
Check if branches are equal and if PR already exists before changing …
saitho Sep 18, 2019
4c8b956
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Sep 18, 2019
b2f8777
Make sure to check all commits
saitho Sep 18, 2019
2c02f4b
Print error messages for user as error flash message
saitho Sep 18, 2019
06adcfd
Disallow changing target branch of closed or merged pull requests
saitho Sep 18, 2019
7454709
Merge branch 'master' into feature/choose_pullreq_target
saitho Nov 20, 2019
bf60f41
Resolve conflicts after merge of upstream/master
saitho Nov 20, 2019
feade60
Change order of branch select fields
saitho Nov 20, 2019
ade1de9
Removes duplicate check
saitho Nov 24, 2019
1094cc0
Use ctx.Tr for translations
saitho Nov 24, 2019
425f631
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Nov 24, 2019
7fa44f3
Recompile JS
saitho Nov 24, 2019
139b7be
Use correct translation namespace
saitho Nov 24, 2019
5d1091b
Remove redundant if condition
saitho Nov 24, 2019
927c82a
Moves most change branch logic into pull service
saitho Nov 25, 2019
8473385
Completes comment
saitho Nov 25, 2019
0a559df
Add Ref to ChangesPayload for logging changed target branches
saitho Nov 25, 2019
234dc2a
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Nov 25, 2019
4104ce6
Revert changes to go.mod
saitho Nov 25, 2019
c2c54b7
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Dec 5, 2019
93ce415
Directly use createComment method
saitho Dec 5, 2019
a040294
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Dec 7, 2019
1566045
Return 404 if pull request is not found. Move written check up
saitho Dec 7, 2019
4c2341a
Remove variable declaration
saitho Dec 9, 2019
8007148
Return client errors on change pull request target errors
saitho Dec 9, 2019
e2d5d0d
Return error in commit.HasPreviousCommit
saitho Dec 12, 2019
2666224
Adds blank line
saitho Dec 12, 2019
c25503a
Test patch before persisting new target branch
saitho Dec 12, 2019
b9c3368
Update patch before testing (not working)
saitho Dec 12, 2019
1dcf6b6
Removes patch calls when changeing pull request target
saitho Dec 14, 2019
6a81a97
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Dec 14, 2019
7db6fc5
Removes unneeded check for base name
saitho Dec 14, 2019
1860253
Moves ChangeTargetBranch completely to pull service. Update patch sta…
saitho Dec 14, 2019
21e1c0b
Set webhook mode after errors were validated
saitho Dec 14, 2019
79347b0
Update PR in one transaction
saitho Dec 14, 2019
7ff8949
Move logic for check if head is equal with branch to pull model
saitho Dec 14, 2019
3a30a60
Adds missing comment and simplify return
saitho Dec 14, 2019
750ba50
Merge branch 'master' into feature/choose_pullreq_target
lunny Dec 14, 2019
69a2926
Merge branch 'master' into feature/choose_pullreq_target
lunny Dec 15, 2019
4e775c6
Merge branch 'master' into feature/choose_pullreq_target
zeripath Dec 15, 2019
cc39ac1
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Dec 15, 2019
ded3b68
Merge branch 'master' into feature/choose_pullreq_target
zeripath Dec 15, 2019
10cb3a5
Merge branch 'master' into feature/choose_pullreq_target
sapk Dec 15, 2019
9c04491
Merge branch 'master' into feature/choose_pullreq_target
lunny Dec 16, 2019
66de122
Merge remote-tracking branch 'upstream/master' into feature/choose_pu…
saitho Dec 16, 2019
23bd8ac
Adjust CreateComment method call
saitho Dec 16, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -118,6 +120,8 @@ type Comment struct {
Assignee *User `xorm:"-"`
OldTitle string
NewTitle string
OldBranch string
NewBranch string
DependentIssueID int64
DependentIssue *Issue `xorm:"-"`

Expand Down Expand Up @@ -552,6 +556,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 @@ -754,6 +760,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 @@ -815,6 +832,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 @@ -240,6 +240,8 @@ var migrations = []Migration{
NewMigration("add index on owner_id of repository and type, review_id of comment", addIndexOnRepositoryAndComment),
// v92 -> v93
NewMigration("remove orphaned repository index statuses", removeLingeringIndexStatus),
// v93 -> v94
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/v93.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 @@ -1160,6 +1160,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 @@ -957,8 +957,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 @@ -790,28 +790,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;
};

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

const baseName = selectionTextField.data('basename');
const branchNameNew = $(this).data('branch');
const 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()) {

const pullrequest_targetbranch_change = function(update_url) {
const 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();
});
};

const 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 @@ -601,6 +601,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 @@ -866,6 +888,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 @@ -432,6 +432,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 @@ -555,6 +556,7 @@ func ViewPullFiles(ctx *context.Context) {
ctx.ServerError("GetCurrentReview", err)
return
}
getBranchData(ctx, issue)
ctx.HTML(200, tplPullFiles)
}

Expand Down Expand Up @@ -991,3 +993,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,
})
}
3 changes: 3 additions & 0 deletions routers/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/compare/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists).
Get(repo.SetDiffViewStyle, repo.CompareDiff).
Post(context.RepoMustNotBeArchived(), reqRepoPullsReader, repo.MustAllowPulls, bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
m.Group("/pull", func() {
m.Post("/:index/target_branch", repo.UpdatePullRequestTarget)
}, 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}}">
{{if .OriginalAuthor }}
Expand Down Expand Up @@ -395,5 +395,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}}
35 changes: 32 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 @@ -37,11 +37,40 @@
{{else}}
{{if .Issue.OriginalAuthor }}
{{.Issue.OriginalAuthor}}
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
<span id="pull-desc" class="pull-desc">{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
{{else}}
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.GetDisplayName}}</a>
<span class="pull-desc">{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
<span id="pull-desc" class="pull-desc">{{$.i18n.Tr "repo.pulls.title_desc" .NumCommits .HeadTarget .BaseTarget | Str2html}}</span>
{{end}}
<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