Skip to content

Commit 1eebbf2

Browse files
authored
When conflicts have been previously detected ensure that they can be resolved (#19247)
There is yet another problem with conflicted files not being reset when the test patch resolves them. This PR adjusts the code for checkConflicts to reset the ConflictedFiles field immediately at the top. It also adds a reset to conflictedFiles for the manuallyMerged and a shortcut for the empty status in protectedfiles. Signed-off-by: Andrew Thornton <[email protected]>
1 parent 66f2210 commit 1eebbf2

File tree

2 files changed

+22
-18
lines changed

2 files changed

+22
-18
lines changed

models/pull.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,11 @@ func (pr *PullRequest) SetMerged() (bool, error) {
424424
return false, fmt.Errorf("Issue.changeStatus: %v", err)
425425
}
426426

427+
// reset the conflicted files as there cannot be any if we're merged
428+
pr.ConflictedFiles = []string{}
429+
427430
// We need to save all of the data used to compute this merge as it may have already been changed by TestPatch. FIXME: need to set some state to prevent TestPatch from running whilst we are merging.
428-
if _, err := sess.Where("id = ?", pr.ID).Cols("has_merged, status, merge_base, merged_commit_id, merger_id, merged_unix").Update(pr); err != nil {
431+
if _, err := sess.Where("id = ?", pr.ID).Cols("has_merged, status, merge_base, merged_commit_id, merger_id, merged_unix, conflicted_files").Update(pr); err != nil {
429432
return false, fmt.Errorf("Failed to update pr[%d]: %v", pr.ID, err)
430433
}
431434

services/pull/patch.go

+18-17
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,10 @@ func AttemptThreeWayMerge(ctx context.Context, gitPath string, gitRepo *git.Repo
270270
}
271271

272272
func checkConflicts(ctx context.Context, pr *models.PullRequest, gitRepo *git.Repository, tmpBasePath string) (bool, error) {
273+
// 1. checkConflicts resets the conflict status - therefore - reset the conflict status
274+
pr.ConflictedFiles = nil
275+
276+
// 2. AttemptThreeWayMerge first - this is much quicker than plain patch to base
273277
description := fmt.Sprintf("PR[%d] %s/%s#%d", pr.ID, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, pr.Index)
274278
conflict, _, err := AttemptThreeWayMerge(ctx,
275279
tmpBasePath, gitRepo, pr.MergeBase, "base", "tracking", description)
@@ -290,16 +294,14 @@ func checkConflicts(ctx context.Context, pr *models.PullRequest, gitRepo *git.Re
290294
if treeHash == baseTree.ID.String() {
291295
log.Debug("PullRequest[%d]: Patch is empty - ignoring", pr.ID)
292296
pr.Status = models.PullRequestStatusEmpty
293-
pr.ConflictedFiles = []string{}
294-
pr.ChangedProtectedFiles = []string{}
295297
}
296298

297299
return false, nil
298300
}
299301

300-
// OK read-tree has failed so we need to try a different thing - this might actually succeed where the above fails due to whitespace handling.
302+
// 3. OK read-tree has failed so we need to try a different thing - this might actually succeed where the above fails due to whitespace handling.
301303

302-
// 1. Create a plain patch from head to base
304+
// 3a. Create a plain patch from head to base
303305
tmpPatchFile, err := os.CreateTemp("", "patch")
304306
if err != nil {
305307
log.Error("Unable to create temporary patch file! Error: %v", err)
@@ -322,34 +324,29 @@ func checkConflicts(ctx context.Context, pr *models.PullRequest, gitRepo *git.Re
322324
patchPath := tmpPatchFile.Name()
323325
tmpPatchFile.Close()
324326

325-
// 1a. if the size of that patch is 0 - there can be no conflicts!
327+
// 3b. if the size of that patch is 0 - there can be no conflicts!
326328
if stat.Size() == 0 {
327329
log.Debug("PullRequest[%d]: Patch is empty - ignoring", pr.ID)
328330
pr.Status = models.PullRequestStatusEmpty
329-
pr.ConflictedFiles = []string{}
330-
pr.ChangedProtectedFiles = []string{}
331331
return false, nil
332332
}
333333

334334
log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
335335

336-
// 2. preset the pr.Status as checking (this is not save at present)
337-
pr.Status = models.PullRequestStatusChecking
338-
339-
// 3. Read the base branch in to the index of the temporary repository
336+
// 4. Read the base branch in to the index of the temporary repository
340337
_, err = git.NewCommand(gitRepo.Ctx, "read-tree", "base").RunInDir(tmpBasePath)
341338
if err != nil {
342339
return false, fmt.Errorf("git read-tree %s: %v", pr.BaseBranch, err)
343340
}
344341

345-
// 4. Now get the pull request configuration to check if we need to ignore whitespace
342+
// 5. Now get the pull request configuration to check if we need to ignore whitespace
346343
prUnit, err := pr.BaseRepo.GetUnit(unit.TypePullRequests)
347344
if err != nil {
348345
return false, err
349346
}
350347
prConfig := prUnit.PullRequestsConfig()
351348

352-
// 5. Prepare the arguments to apply the patch against the index
349+
// 6. Prepare the arguments to apply the patch against the index
353350
args := []string{"apply", "--check", "--cached"}
354351
if prConfig.IgnoreWhitespaceConflicts {
355352
args = append(args, "--ignore-whitespace")
@@ -360,9 +357,8 @@ func checkConflicts(ctx context.Context, pr *models.PullRequest, gitRepo *git.Re
360357
is3way = true
361358
}
362359
args = append(args, patchPath)
363-
pr.ConflictedFiles = make([]string, 0, 5)
364360

365-
// 6. Prep the pipe:
361+
// 7. Prep the pipe:
366362
// - Here we could do the equivalent of:
367363
// `git apply --check --cached patch_file > conflicts`
368364
// Then iterate through the conflicts. However, that means storing all the conflicts
@@ -380,7 +376,7 @@ func checkConflicts(ctx context.Context, pr *models.PullRequest, gitRepo *git.Re
380376
_ = stderrWriter.Close()
381377
}()
382378

383-
// 7. Run the check command
379+
// 8. Run the check command
384380
conflict = false
385381
err = git.NewCommand(gitRepo.Ctx, args...).
386382
RunWithContext(&git.RunContext{
@@ -448,7 +444,7 @@ func checkConflicts(ctx context.Context, pr *models.PullRequest, gitRepo *git.Re
448444
},
449445
})
450446

451-
// 8. If there is a conflict the `git apply` command will return a non-zero error code - so there will be a positive error.
447+
// 9. If there is a conflict the `git apply` command will return a non-zero error code - so there will be a positive error.
452448
if err != nil {
453449
if conflict {
454450
pr.Status = models.PullRequestStatusConflict
@@ -518,6 +514,11 @@ func CheckUnprotectedFiles(repo *git.Repository, oldCommitID, newCommitID string
518514

519515
// checkPullFilesProtection check if pr changed protected files and save results
520516
func checkPullFilesProtection(pr *models.PullRequest, gitRepo *git.Repository) error {
517+
if pr.Status == models.PullRequestStatusEmpty {
518+
pr.ChangedProtectedFiles = nil
519+
return nil
520+
}
521+
521522
if err := pr.LoadProtectedBranch(); err != nil {
522523
return err
523524
}

0 commit comments

Comments
 (0)