Skip to content

Pull request conflict files detection #5951

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 5 commits into from
Feb 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
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
35 changes: 30 additions & 5 deletions models/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ const (

// PullRequest represents relation between pull request and repositories.
type PullRequest struct {
ID int64 `xorm:"pk autoincr"`
Type PullRequestType
Status PullRequestStatus
ID int64 `xorm:"pk autoincr"`
Type PullRequestType
Status PullRequestStatus
ConflictedFiles []string `xorm:"TEXT JSON"`

IssueID int64 `xorm:"INDEX"`
Issue *Issue `xorm:"-"`
Expand Down Expand Up @@ -843,6 +844,7 @@ func (pr *PullRequest) testPatch(e Engine) (err error) {
args = append(args, "--ignore-whitespace")
}
args = append(args, patchPath)
pr.ConflictedFiles = []string{}

_, 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()},
Expand All @@ -851,8 +853,26 @@ func (pr *PullRequest) testPatch(e Engine) (err error) {
for i := range patchConflicts {
if strings.Contains(stderr, patchConflicts[i]) {
log.Trace("PullRequest[%d].testPatch (apply): has conflict", pr.ID)
fmt.Println(stderr)
const prefix = "error: patch failed:"
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
}
}
Expand Down Expand Up @@ -1375,7 +1395,7 @@ func (pr *PullRequest) checkAndUpdateStatus() {

// Make sure there is no waiting test to process before leaving the checking status.
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)
}
}
Expand All @@ -1396,6 +1416,11 @@ func (pr *PullRequest) IsWorkInProgress() bool {
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.
// It returns an empty string when none were found
func (pr *PullRequest) GetWorkInProgressPrefix() string {
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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.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.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.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.
Expand Down
5 changes: 5 additions & 0 deletions routers/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullReq
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["NumFiles"] = prInfo.NumFiles
return prInfo
Expand Down
9 changes: 9 additions & 0 deletions templates/repo/issue/view_content/pull.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
{{if .Issue.PullRequest.HasMerged}}purple
{{else if .Issue.IsClosed}}grey
{{else if .IsPullWorkInProgress}}grey
{{else if .IsFilesConflicted}}grey
{{else if .IsPullRequestBroken}}red
{{else if .IsBlockedByApprovals}}red
{{else if .Issue.PullRequest.IsChecking}}yellow
Expand All @@ -59,6 +60,14 @@
<div class="item text grey">
{{$.i18n.Tr "repo.pulls.reopen_to_merge"}}
</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}}
<div class="item text red">
<span class="octicon octicon-x"></span>
Expand Down