Skip to content

Commit c39e0b3

Browse files
committed
Speed up conflict checking in pull request creation
In order to check conflicts of a PR, we set up a working tree by cloning the base branch, which is quite time-consuming when the repository is huge. Instead, this PR uses `git read-tree` and `git apply --check --cached` to check conflicts. For go-gitea#258
1 parent 799d0c2 commit c39e0b3

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

models/pull.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"fmt"
99
"os"
1010
"path"
11+
"path/filepath"
12+
"strconv"
1113
"strings"
1214
"time"
1315

@@ -428,17 +430,22 @@ func (pr *PullRequest) testPatch() (err error) {
428430

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

431-
// Delete old temp local copy before we create a new temp local copy
432-
RemoveAllWithNotice("Deleting old local copy", pr.BaseRepo.LocalCopyPath())
433+
pr.Status = PullRequestStatusChecking
434+
435+
indexTmpPath := filepath.Join(os.TempDir(), "-gitea-"+pr.BaseRepo.Name+"-"+strconv.Itoa(time.Now().Nanosecond()))
436+
defer os.Remove(indexTmpPath)
433437

434-
if err := pr.BaseRepo.UpdateLocalCopyBranch(pr.BaseBranch); err != nil {
435-
return fmt.Errorf("UpdateLocalCopy: %v", err)
438+
var stderr string
439+
_, stderr, err = process.ExecDirEnv(-1, "", fmt.Sprintf("testPatch (git read-tree): %d", pr.BaseRepo.ID),
440+
[]string{"GIT_DIR=" + pr.BaseRepo.RepoPath()},
441+
"git", "read-tree", "--index-output", indexTmpPath, pr.BaseBranch)
442+
if err != nil {
443+
return fmt.Errorf("git read-tree --index-output=%s %s: %v - %s", indexTmpPath, pr.BaseBranch, err, stderr)
436444
}
437445

438-
pr.Status = PullRequestStatusChecking
439-
_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
440-
fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
441-
"git", "apply", "--check", patchPath)
446+
_, stderr, err = process.ExecDirEnv(-1, "", fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
447+
[]string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()},
448+
"git", "apply", "--check", "--cached", patchPath)
442449
if err != nil {
443450
for i := range patchConflicts {
444451
if strings.Contains(stderr, patchConflicts[i]) {

0 commit comments

Comments
 (0)