mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-09 08:07:40 +00:00
feat: improved performances when checking for conflicts on pull requests (#7727)
Some checks are pending
/ release (push) Waiting to run
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
Some checks are pending
/ release (push) Waiting to run
testing / backend-checks (push) Waiting to run
testing / frontend-checks (push) Waiting to run
testing / test-unit (push) Blocked by required conditions
testing / test-e2e (push) Blocked by required conditions
testing / test-remote-cacher (redis) (push) Blocked by required conditions
testing / test-remote-cacher (valkey) (push) Blocked by required conditions
testing / test-remote-cacher (garnet) (push) Blocked by required conditions
testing / test-remote-cacher (redict) (push) Blocked by required conditions
testing / test-mysql (push) Blocked by required conditions
testing / test-pgsql (push) Blocked by required conditions
testing / test-sqlite (push) Blocked by required conditions
testing / security-check (push) Blocked by required conditions
- `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
62
services/pull/patch_test.go
Normal file
62
services/pull/patch_test.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package pull
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
issues_model "forgejo.org/models/issues"
|
||||
"forgejo.org/models/unittest"
|
||||
"forgejo.org/modules/setting"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestLoadHeadRevision(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
t.Run("AGit", func(t *testing.T) {
|
||||
t.Run("New", func(t *testing.T) {
|
||||
ctx := &testPatchContext{}
|
||||
require.NoError(t, ctx.LoadHeadRevision(t.Context(), &issues_model.PullRequest{Flow: issues_model.PullRequestFlowAGit, HeadCommitID: "Commit!"}))
|
||||
|
||||
assert.Empty(t, ctx.env)
|
||||
assert.Equal(t, "Commit!", ctx.headRev)
|
||||
assert.True(t, ctx.headIsCommitID)
|
||||
})
|
||||
t.Run("Existing", func(t *testing.T) {
|
||||
ctx := &testPatchContext{}
|
||||
require.NoError(t, ctx.LoadHeadRevision(t.Context(), &issues_model.PullRequest{Flow: issues_model.PullRequestFlowAGit, Index: 371}))
|
||||
|
||||
assert.Empty(t, ctx.env)
|
||||
assert.Equal(t, "refs/pull/371/head", ctx.headRev)
|
||||
assert.False(t, ctx.headIsCommitID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Same repository", func(t *testing.T) {
|
||||
ctx := &testPatchContext{}
|
||||
require.NoError(t, ctx.LoadHeadRevision(t.Context(), unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})))
|
||||
|
||||
assert.Empty(t, ctx.env)
|
||||
assert.Equal(t, "refs/heads/branch1", ctx.headRev)
|
||||
assert.False(t, ctx.headIsCommitID)
|
||||
})
|
||||
|
||||
t.Run("Across repository", func(t *testing.T) {
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 3})
|
||||
require.NoError(t, pr.LoadHeadRepo(t.Context()))
|
||||
|
||||
ctx := &testPatchContext{}
|
||||
require.NoError(t, ctx.LoadHeadRevision(t.Context(), pr))
|
||||
|
||||
if assert.NotEmpty(t, ctx.env) {
|
||||
assert.Equal(t, fmt.Sprintf("GIT_ALTERNATE_OBJECT_DIRECTORIES=%s/user13/repo11.git/objects", setting.RepoRootPath), ctx.env[len(ctx.env)-1])
|
||||
}
|
||||
assert.Equal(t, "0abcb056019adb8336cf9db3ad9d9cf80cd4b141", ctx.headRev)
|
||||
assert.True(t, ctx.headIsCommitID)
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue