mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-08-05 09:55:20 +02:00
feat: improved performances when checking for conflicts on pull requests (#7727)
- `testPatch` is a function that is called to test a pull request and determine the state of the pull request. Checking for merge conflicts, check if the diff is empty and if the pull request modifies any protected files. - The checking for merge conflict and if the diff is empty used git commands that relied on a working tree to correctly functions. Forgejo store repositories in a bare format which do not contain a working tree. This means that a temporary copy was created every time a pull request had to be re-checked and for large repositories involving quite some I/O interaction. - This patch adjusts those codepaths to instead use newer Git plumbing commands that work without requiring a work tree and can thus be used directly on the bare repository. The merge conflict is now done via [`git-merge-tree(1)`](https://git-scm.com/docs/git-merge-tree/) and checking if the diff is empty is done via [`git-diff-tree(1)`](https://git-scm.com/docs/git-diff-tree). - If the function is called to test a patch where the head and base repository are not the same, then [Git alternate](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefalternateobjectdatabaseaalternateobjectdatabase) is used to make the head commit available in the base repository, this done on a per git command basis via the `GIT_ALTERNATE_OBJECT_DIRECTORIES` environment. - As far as I can understand the documentation and the existing code, there's no edge case that the new code cannot handle. It also results in a cleaner codepath, as the existing code did a lot of checking and merging in a more traditional approach that required a lot of (parsing) code, while the new code offloads this to git and has a trivial parser of the output. - Resolves forgejo/forgejo#7701 - Added exhaustive integration testing. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7727 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Reviewed-by: Otto <otto@codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
parent
2ab5b585f6
commit
7c150be23d
13 changed files with 645 additions and 156 deletions
|
@ -79,21 +79,33 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod
|
|||
right, base = base, right
|
||||
}
|
||||
|
||||
description := fmt.Sprintf("CherryPick %s onto %s", right, opts.OldBranch)
|
||||
conflict, _, err := pull.AttemptThreeWayMerge(ctx,
|
||||
t.basePath, t.gitRepo, base, opts.LastCommitID, right, description)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to three-way merge %s onto %s: %w", right, opts.OldBranch, err)
|
||||
}
|
||||
var treeHash string
|
||||
if git.SupportGitMergeTree {
|
||||
var conflict bool
|
||||
treeHash, conflict, _, err = pull.MergeTree(ctx, t.gitRepo, base, opts.LastCommitID, right, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to three-way merge %s onto %s: %w", right, opts.OldBranch, err)
|
||||
}
|
||||
|
||||
if conflict {
|
||||
return nil, fmt.Errorf("failed to merge due to conflicts")
|
||||
}
|
||||
if conflict {
|
||||
return nil, fmt.Errorf("failed to merge due to conflicts")
|
||||
}
|
||||
} else {
|
||||
description := fmt.Sprintf("CherryPick %s onto %s", right, opts.OldBranch)
|
||||
conflict, _, err := pull.AttemptThreeWayMerge(ctx, t.gitRepo, base, opts.LastCommitID, right, description)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to three-way merge %s onto %s: %w", right, opts.OldBranch, err)
|
||||
}
|
||||
|
||||
treeHash, err := t.WriteTree()
|
||||
if err != nil {
|
||||
// likely non-sensical tree due to merge conflicts...
|
||||
return nil, err
|
||||
if conflict {
|
||||
return nil, fmt.Errorf("failed to merge due to conflicts")
|
||||
}
|
||||
|
||||
treeHash, err = t.WriteTree()
|
||||
if err != nil {
|
||||
// likely non-sensical tree due to merge conflicts...
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Now commit the tree
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
// CountDivergingCommits determines how many commits a branch is ahead or behind the repository's base branch
|
||||
func CountDivergingCommits(ctx context.Context, repo *repo_model.Repository, branch string) (*git.DivergeObject, error) {
|
||||
divergence, err := git.GetDivergingCommits(ctx, repo.RepoPath(), repo.DefaultBranch, branch)
|
||||
divergence, err := git.GetDivergingCommits(ctx, repo.RepoPath(), repo.DefaultBranch, branch, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue