mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	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.
This commit is contained in:
		
				
					committed by
					
						 Lauris BH
						Lauris BH
					
				
			
			
				
	
			
			
			
						parent
						
							0de57fd57c
						
					
				
				
					commit
					9f476b8d1e
				
			| @@ -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] | ||||
| @@ -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 | ||||
| 			} | ||||
| 		} | ||||
| @@ -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) | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -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: "user2@example.com", | ||||
| 			CommitterName:  "User Two", | ||||
| 			AuthorEmail:    "user4@example.com", | ||||
| 			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) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user