Pull request conflict files detection (#5951)
* add conflict detection * test pull request conflict files * fix detection files number * fix comments
This commit is contained in:
parent
680a57ce92
commit
bf4badad1d
4 changed files with 45 additions and 5 deletions
|
@ -57,6 +57,7 @@ type PullRequest struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
Type PullRequestType
|
Type PullRequestType
|
||||||
Status PullRequestStatus
|
Status PullRequestStatus
|
||||||
|
ConflictedFiles []string `xorm:"TEXT JSON"`
|
||||||
|
|
||||||
IssueID int64 `xorm:"INDEX"`
|
IssueID int64 `xorm:"INDEX"`
|
||||||
Issue *Issue `xorm:"-"`
|
Issue *Issue `xorm:"-"`
|
||||||
|
@ -843,6 +844,7 @@ func (pr *PullRequest) testPatch(e Engine) (err error) {
|
||||||
args = append(args, "--ignore-whitespace")
|
args = append(args, "--ignore-whitespace")
|
||||||
}
|
}
|
||||||
args = append(args, patchPath)
|
args = append(args, patchPath)
|
||||||
|
pr.ConflictedFiles = []string{}
|
||||||
|
|
||||||
_, stderr, err = process.GetManager().ExecDirEnv(-1, "", fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
|
_, stderr, err = process.GetManager().ExecDirEnv(-1, "", fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
|
||||||
[]string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()},
|
[]string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()},
|
||||||
|
@ -851,8 +853,26 @@ func (pr *PullRequest) testPatch(e Engine) (err error) {
|
||||||
for i := range patchConflicts {
|
for i := range patchConflicts {
|
||||||
if strings.Contains(stderr, patchConflicts[i]) {
|
if strings.Contains(stderr, patchConflicts[i]) {
|
||||||
log.Trace("PullRequest[%d].testPatch (apply): has conflict", pr.ID)
|
log.Trace("PullRequest[%d].testPatch (apply): has conflict", pr.ID)
|
||||||
fmt.Println(stderr)
|
const prefix = "error: patch failed:"
|
||||||
pr.Status = PullRequestStatusConflict
|
pr.Status = PullRequestStatusConflict
|
||||||
|
pr.ConflictedFiles = make([]string, 0, 5)
|
||||||
|
scanner := bufio.NewScanner(strings.NewReader(stderr))
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, prefix) {
|
||||||
|
pr.ConflictedFiles = append(pr.ConflictedFiles, strings.TrimSpace(strings.Split(line[len(prefix):], ":")[0]))
|
||||||
|
}
|
||||||
|
// only list 10 conflicted files
|
||||||
|
if len(pr.ConflictedFiles) >= 10 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pr.ConflictedFiles) > 0 {
|
||||||
|
log.Trace("Found %d files conflicted: %v", len(pr.ConflictedFiles), pr.ConflictedFiles)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1375,7 +1395,7 @@ func (pr *PullRequest) checkAndUpdateStatus() {
|
||||||
|
|
||||||
// Make sure there is no waiting test to process before leaving the checking status.
|
// Make sure there is no waiting test to process before leaving the checking status.
|
||||||
if !pullRequestQueue.Exist(pr.ID) {
|
if !pullRequestQueue.Exist(pr.ID) {
|
||||||
if err := pr.UpdateCols("status"); err != nil {
|
if err := pr.UpdateCols("status, conflicted_files"); err != nil {
|
||||||
log.Error(4, "Update[%d]: %v", pr.ID, err)
|
log.Error(4, "Update[%d]: %v", pr.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1396,6 +1416,11 @@ func (pr *PullRequest) IsWorkInProgress() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsFilesConflicted determines if the Pull Request has changes conflicting with the target branch.
|
||||||
|
func (pr *PullRequest) IsFilesConflicted() bool {
|
||||||
|
return len(pr.ConflictedFiles) > 0
|
||||||
|
}
|
||||||
|
|
||||||
// GetWorkInProgressPrefix returns the prefix used to mark the pull request as a work in progress.
|
// GetWorkInProgressPrefix returns the prefix used to mark the pull request as a work in progress.
|
||||||
// It returns an empty string when none were found
|
// It returns an empty string when none were found
|
||||||
func (pr *PullRequest) GetWorkInProgressPrefix() string {
|
func (pr *PullRequest) GetWorkInProgressPrefix() string {
|
||||||
|
|
|
@ -872,6 +872,7 @@ pulls.has_merged = The pull request has been merged.
|
||||||
pulls.title_wip_desc = `<a href="#">Start the title with <strong>%s</strong></a> to prevent the pull request from being merged accidentally.`
|
pulls.title_wip_desc = `<a href="#">Start the title with <strong>%s</strong></a> to prevent the pull request from being merged accidentally.`
|
||||||
pulls.cannot_merge_work_in_progress = This pull request is marked as a work in progress. Remove the <strong>%s</strong> prefix from the title when it's ready
|
pulls.cannot_merge_work_in_progress = This pull request is marked as a work in progress. Remove the <strong>%s</strong> prefix from the title when it's ready
|
||||||
pulls.data_broken = This pull request is broken due to missing fork information.
|
pulls.data_broken = This pull request is broken due to missing fork information.
|
||||||
|
pulls.files_conflicted = This pull request has changes conflicting with the target branch.
|
||||||
pulls.is_checking = "Merge conflict checking is in progress. Try again in few moments."
|
pulls.is_checking = "Merge conflict checking is in progress. Try again in few moments."
|
||||||
pulls.blocked_by_approvals = "This Pull Request doesn't have enough approvals yet. %d of %d approvals granted."
|
pulls.blocked_by_approvals = "This Pull Request doesn't have enough approvals yet. %d of %d approvals granted."
|
||||||
pulls.can_auto_merge_desc = This pull request can be merged automatically.
|
pulls.can_auto_merge_desc = This pull request can be merged automatically.
|
||||||
|
|
|
@ -345,6 +345,11 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullReq
|
||||||
ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix()
|
ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pull.IsFilesConflicted() {
|
||||||
|
ctx.Data["IsPullFilesConflicted"] = true
|
||||||
|
ctx.Data["ConflictedFiles"] = pull.ConflictedFiles
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["NumCommits"] = prInfo.Commits.Len()
|
ctx.Data["NumCommits"] = prInfo.Commits.Len()
|
||||||
ctx.Data["NumFiles"] = prInfo.NumFiles
|
ctx.Data["NumFiles"] = prInfo.NumFiles
|
||||||
return prInfo
|
return prInfo
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
{{if .Issue.PullRequest.HasMerged}}purple
|
{{if .Issue.PullRequest.HasMerged}}purple
|
||||||
{{else if .Issue.IsClosed}}grey
|
{{else if .Issue.IsClosed}}grey
|
||||||
{{else if .IsPullWorkInProgress}}grey
|
{{else if .IsPullWorkInProgress}}grey
|
||||||
|
{{else if .IsFilesConflicted}}grey
|
||||||
{{else if .IsPullRequestBroken}}red
|
{{else if .IsPullRequestBroken}}red
|
||||||
{{else if .IsBlockedByApprovals}}red
|
{{else if .IsBlockedByApprovals}}red
|
||||||
{{else if .Issue.PullRequest.IsChecking}}yellow
|
{{else if .Issue.PullRequest.IsChecking}}yellow
|
||||||
|
@ -59,6 +60,14 @@
|
||||||
<div class="item text grey">
|
<div class="item text grey">
|
||||||
{{$.i18n.Tr "repo.pulls.reopen_to_merge"}}
|
{{$.i18n.Tr "repo.pulls.reopen_to_merge"}}
|
||||||
</div>
|
</div>
|
||||||
|
{{else if .IsPullFilesConflicted}}
|
||||||
|
<div class="item text grey">
|
||||||
|
<span class="octicon octicon-x"></span>
|
||||||
|
{{$.i18n.Tr "repo.pulls.files_conflicted"}}
|
||||||
|
{{range .ConflictedFiles}}
|
||||||
|
<div>{{.}}</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
{{else if .IsPullRequestBroken}}
|
{{else if .IsPullRequestBroken}}
|
||||||
<div class="item text red">
|
<div class="item text red">
|
||||||
<span class="octicon octicon-x"></span>
|
<span class="octicon octicon-x"></span>
|
||||||
|
|
Reference in a new issue