From bf4badad1d68c18d7ffb92c69e09e4e8aa252935 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 5 Feb 2019 19:54:49 +0800 Subject: [PATCH] Pull request conflict files detection (#5951) * add conflict detection * test pull request conflict files * fix detection files number * fix comments --- models/pull.go | 35 ++++++++++++++++++--- options/locale/locale_en-US.ini | 1 + routers/repo/pull.go | 5 +++ templates/repo/issue/view_content/pull.tmpl | 9 ++++++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/models/pull.go b/models/pull.go index d84be139c..35fbc4178 100644 --- a/models/pull.go +++ b/models/pull.go @@ -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:"-"` @@ -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()}, @@ -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 } } @@ -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) } } @@ -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 { diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 502b980c4..f83ad15b3 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -872,6 +872,7 @@ pulls.has_merged = The pull request has been merged. pulls.title_wip_desc = `Start the title with %s 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 %s 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. diff --git a/routers/repo/pull.go b/routers/repo/pull.go index c060aeb4b..a65b68a96 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -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 diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index 72808d089..0ddb2820f 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -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 @@ -59,6 +60,14 @@
{{$.i18n.Tr "repo.pulls.reopen_to_merge"}}
+ {{else if .IsPullFilesConflicted}} +
+ + {{$.i18n.Tr "repo.pulls.files_conflicted"}} + {{range .ConflictedFiles}} +
{{.}}
+ {{end}} +
{{else if .IsPullRequestBroken}}