Skip to content

Commit d6b9662

Browse files
zeripathlunnyKN4CK3R
authored
Add setting to disable the git apply step in test patch (#22130)
For a long time Gitea has tested PR patches using a git apply --check method, and in fact prior to the introduction of a read-tree assisted three-way merge in #18004, this was the only way of checking patches. Since #18004, the git apply --check method has been a fallback method, only used when the read-tree three-way merge method has detected a conflict. The read-tree assisted three-way merge method is much faster and less resource intensive method of detecting conflicts. #18004 kept the git apply method around because it was thought possible that this fallback might be able to rectify conflicts that the read-tree three-way merge detected. I am not certain if this could ever be the case. Given the uncertainty here and the now relative stability of the read-tree method - this PR makes using this fallback optional and disables it by default. The hope is that users will not notice any significant difference in conflict detection and we will be able to remove the git apply fallback in future, and/or improve the read-tree three-way merge method to catch any conflicts that git apply method might have been able to fix. An additional benefit is that patch checking should be significantly less resource intensive and much quicker. (See https://github.com/go-gitea/gitea/issues/22083\#issuecomment-1347961737) Ref #22083 Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
1 parent a89b399 commit d6b9662

File tree

4 files changed

+23
-4
lines changed

4 files changed

+23
-4
lines changed

custom/conf/app.example.ini

+3
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,9 @@ ROUTER = console
10361036
;;
10371037
;; Add co-authored-by and co-committed-by trailers if committer does not match author
10381038
;ADD_CO_COMMITTER_TRAILERS = true
1039+
;;
1040+
;; In addition to testing patches using the three-way merge method, re-test conflicting patches with git apply
1041+
;TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY = false
10391042

10401043
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10411044
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

docs/content/doc/advanced/config-cheat-sheet.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build
134134
- `DEFAULT_MERGE_MESSAGE_OFFICIAL_APPROVERS_ONLY`: **true**: In default merge messages only include approvers who are officially allowed to review.
135135
- `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`: **false**: In default squash-merge messages include the commit message of all commits comprising the pull request.
136136
- `ADD_CO_COMMITTER_TRAILERS`: **true**: Add co-authored-by and co-committed-by trailers to merge commit messages if committer does not match author.
137+
- `TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY`: **false**: PR patches are tested using a three-way merge method to discover if there are conflicts. If this setting is set to **true**, conflicting patches will be retested using `git apply` - This was the previous behaviour in 1.18 (and earlier) but is somewhat inefficient. Please report if you find that this setting is required.
137138

138139
### Repository - Issue (`repository.issue`)
139140

modules/setting/repository.go

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ var (
8282
DefaultMergeMessageOfficialApproversOnly bool
8383
PopulateSquashCommentWithCommitMessages bool
8484
AddCoCommitterTrailers bool
85+
TestConflictingPatchesWithGitApply bool
8586
} `ini:"repository.pull-request"`
8687

8788
// Issue Setting
@@ -204,6 +205,7 @@ var (
204205
DefaultMergeMessageOfficialApproversOnly bool
205206
PopulateSquashCommentWithCommitMessages bool
206207
AddCoCommitterTrailers bool
208+
TestConflictingPatchesWithGitApply bool
207209
}{
208210
WorkInProgressPrefixes: []string{"WIP:", "[WIP]"},
209211
// Same as GitHub. See

services/pull/patch.go

+17-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"code.gitea.io/gitea/modules/log"
2424
"code.gitea.io/gitea/modules/process"
2525
repo_module "code.gitea.io/gitea/modules/repository"
26+
"code.gitea.io/gitea/modules/setting"
2627
"code.gitea.io/gitea/modules/util"
2728

2829
"github.com/gobwas/glob"
@@ -289,13 +290,15 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
289290

290291
// 2. AttemptThreeWayMerge first - this is much quicker than plain patch to base
291292
description := fmt.Sprintf("PR[%d] %s/%s#%d", pr.ID, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, pr.Index)
292-
conflict, _, err := AttemptThreeWayMerge(ctx,
293+
conflict, conflictFiles, err := AttemptThreeWayMerge(ctx,
293294
tmpBasePath, gitRepo, pr.MergeBase, "base", "tracking", description)
294295
if err != nil {
295296
return false, err
296297
}
297298

298299
if !conflict {
300+
// No conflicts detected so we need to check if the patch is empty...
301+
// a. Write the newly merged tree and check the new tree-hash
299302
var treeHash string
300303
treeHash, _, err = git.NewCommand(ctx, "write-tree").RunStdString(&git.RunOpts{Dir: tmpBasePath})
301304
if err != nil {
@@ -307,6 +310,8 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
307310
if err != nil {
308311
return false, err
309312
}
313+
314+
// b. compare the new tree-hash with the base tree hash
310315
if treeHash == baseTree.ID.String() {
311316
log.Debug("PullRequest[%d]: Patch is empty - ignoring", pr.ID)
312317
pr.Status = issues_model.PullRequestStatusEmpty
@@ -315,9 +320,17 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
315320
return false, nil
316321
}
317322

318-
// 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.
323+
// 3. OK the three-way merge method has detected conflicts
324+
// 3a. Are still testing with GitApply? If not set the conflict status and move on
325+
if !setting.Repository.PullRequest.TestConflictingPatchesWithGitApply {
326+
pr.Status = issues_model.PullRequestStatusConflict
327+
pr.ConflictedFiles = conflictFiles
328+
329+
log.Trace("Found %d files conflicted: %v", len(pr.ConflictedFiles), pr.ConflictedFiles)
330+
return true, nil
331+
}
319332

320-
// 3a. Create a plain patch from head to base
333+
// 3b. Create a plain patch from head to base
321334
tmpPatchFile, err := os.CreateTemp("", "patch")
322335
if err != nil {
323336
log.Error("Unable to create temporary patch file! Error: %v", err)
@@ -340,7 +353,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
340353
patchPath := tmpPatchFile.Name()
341354
tmpPatchFile.Close()
342355

343-
// 3b. if the size of that patch is 0 - there can be no conflicts!
356+
// 3c. if the size of that patch is 0 - there can be no conflicts!
344357
if stat.Size() == 0 {
345358
log.Debug("PullRequest[%d]: Patch is empty - ignoring", pr.ID)
346359
pr.Status = issues_model.PullRequestStatusEmpty

0 commit comments

Comments
 (0)