Skip to content
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

Don't close issues via commits on non-default branch. (Backport PR #5622 to v1.7) #5643

Merged
merged 2 commits into from
Jan 5, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Next Next commit
Don't close issues via commits on non-default branch. (#5622)
Adds a small check to close the issues only if the referencing commits
are on the default branch.

Fixes: #2314.
  • Loading branch information
HarshitOnGitHub committed Jan 5, 2019
commit c4e6479b1651f0021810ac4c22f4ca2d6e964d86
74 changes: 35 additions & 39 deletions models/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,34 @@ func getIssueFromRef(repo *Repository, ref string) (*Issue, error) {
return issue, nil
}

func changeIssueStatus(repo *Repository, doer *User, ref string, refMarked map[int64]bool, status bool) error {
issue, err := getIssueFromRef(repo, ref)
if err != nil {
return err
}

if issue == nil || refMarked[issue.ID] {
return nil
}
refMarked[issue.ID] = true

if issue.RepoID != repo.ID || issue.IsClosed == status {
return nil
}

issue.Repo = repo
if err = issue.ChangeStatus(doer, status); err != nil {
// Don't return an error when dependencies are open as this would let the push fail
if IsErrDependenciesLeft(err) {
return nil
}
return err
}
return nil
}

// UpdateIssuesCommit checks if issues are manipulated by commit message.
func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) error {
func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit, branchName string) error {
// Commits are appended in the reverse order.
for i := len(commits) - 1; i >= 0; i-- {
c := commits[i]
Expand All @@ -500,51 +526,21 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
}
}

// Change issue status only if the commit has been pushed to the default branch.
if repo.DefaultBranch != branchName {
continue
}

refMarked = make(map[int64]bool)
// FIXME: can merge this one and next one to a common function.
for _, ref := range issueCloseKeywordsPat.FindAllString(c.Message, -1) {
issue, err := getIssueFromRef(repo, ref)
if err != nil {
return err
}

if issue == nil || refMarked[issue.ID] {
continue
}
refMarked[issue.ID] = true

if issue.RepoID != repo.ID || issue.IsClosed {
continue
}

issue.Repo = repo
if err = issue.ChangeStatus(doer, true); err != nil {
// Don't return an error when dependencies are open as this would let the push fail
if IsErrDependenciesLeft(err) {
return nil
}
if err := changeIssueStatus(repo, doer, ref, refMarked, true); err != nil {
return err
}
}

// It is conflict to have close and reopen at same time, so refsMarked doesn't need to reinit here.
for _, ref := range issueReopenKeywordsPat.FindAllString(c.Message, -1) {
issue, err := getIssueFromRef(repo, ref)
if err != nil {
return err
}

if issue == nil || refMarked[issue.ID] {
continue
}
refMarked[issue.ID] = true

if issue.RepoID != repo.ID || !issue.IsClosed {
continue
}

issue.Repo = repo
if err = issue.ChangeStatus(doer, false); err != nil {
if err := changeIssueStatus(repo, doer, ref, refMarked, false); err != nil {
return err
}
}
Expand Down Expand Up @@ -609,7 +605,7 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID)
}

if err = UpdateIssuesCommit(pusher, repo, opts.Commits.Commits); err != nil {
if err = UpdateIssuesCommit(pusher, repo, opts.Commits.Commits, refName); err != nil {
log.Error(4, "updateIssuesCommit: %v", err)
}
}
Expand Down
29 changes: 28 additions & 1 deletion models/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,37 @@ func TestUpdateIssuesCommit(t *testing.T) {

AssertNotExistsBean(t, commentBean)
AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits))
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
AssertExistsAndLoadBean(t, commentBean)
AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
CheckConsistencyFor(t, &Action{})

// Test that push to a non-default branch closes no issue.
pushCommits = []*PushCommit{
{
Sha1: "abcdef1",
CommitterEmail: "[email protected]",
CommitterName: "User Two",
AuthorEmail: "[email protected]",
AuthorName: "User Four",
Message: "close #1",
},
}
repo = AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository)
commentBean = &Comment{
Type: CommentTypeCommitRef,
CommitSHA: "abcdef1",
PosterID: user.ID,
IssueID: 6,
}
issueBean = &Issue{RepoID: repo.ID, Index: 1}

AssertNotExistsBean(t, commentBean)
AssertNotExistsBean(t, &Issue{RepoID: repo.ID, Index: 1}, "is_closed=1")
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, "non-existing-branch"))
AssertExistsAndLoadBean(t, commentBean)
AssertNotExistsBean(t, issueBean, "is_closed=1")
CheckConsistencyFor(t, &Action{})
}

func testCorrectRepoAction(t *testing.T, opts CommitRepoActionOptions, actionBean *Action) {
Expand Down