enhance!: raise minimum git version to 2.34 (#39565)

Raise the minimum git version to 2.34, the version in Ubuntu 22.04,
Debian 12 and RHEL 8 ship newer, and remove the fallbacks it makes
obsolete.

- Always enable AGit
- Use `diff --skip-to` and `apply -3` unconditionally
- Set the default branch of new repos and wikis via `git init
--initial-branch`
- Detect rebase conflicts via `REBASE_HEAD`
This commit is contained in:
silverwind authored and GitHub committed 2026-10-04 16:26:14 +08:00
1 parent 4bebd86285
commit eb4468ff4e
38 files changed
+177 -404

No files matched your search

+3 -3
View File
@@ -63,7 +63,7 @@ func TestAPIViewPulls(t *testing.T) {
resp = ctx.Session.MakeRequest(t, NewRequest(t, "GET", pull.DiffURL), http.StatusOK)
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs), "")
patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs))
assert.NoError(t, err)
if assert.Len(t, patch.Files, 1) {
assert.Equal(t, "File-WoW", patch.Files[0].Name)
@@ -100,7 +100,7 @@ func TestAPIViewPulls(t *testing.T) {
resp = ctx.Session.MakeRequest(t, NewRequest(t, "GET", pull.DiffURL), http.StatusOK)
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs), "")
patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs))
assert.NoError(t, err)
if assert.Len(t, patch.Files, 1) {
assert.Equal(t, "README.md", patch.Files[0].Name)
@@ -133,7 +133,7 @@ func TestAPIViewPulls(t *testing.T) {
resp = ctx.Session.MakeRequest(t, NewRequest(t, "GET", pull.DiffURL), http.StatusOK)
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs), "")
patch, err := gitdiff.ParsePatch(t.Context(), 1000, 5000, 10, bytes.NewReader(bs))
assert.NoError(t, err)
assert.Len(t, patch.Files, 1)
+53 -50
View File
@@ -5,72 +5,75 @@ package integration
import (
"net/http"
"net/url"
"testing"
deploykey_model "gitea.dev/models/deploykey"
"gitea.dev/models/perm"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
lfs_module "gitea.dev/modules/lfs"
"gitea.dev/modules/setting"
"gitea.dev/modules/test"
"gitea.dev/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDeployTokenGitHTTP(t *testing.T) {
defer tests.PrepareTestEnv(t)()
onGiteaRun(t, func(t *testing.T, u *url.URL) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
otherRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
readKey, err := deploykey_model.AddDeployKeyToken(t.Context(), repo.ID, "read", perm.AccessModeRead)
require.NoError(t, err)
writeKey, err := deploykey_model.AddDeployKeyToken(t.Context(), repo.ID, "write", perm.AccessModeWrite)
require.NoError(t, err)
// need to disable agit, otherwise the "write" permission check is skipped at pre-receive (git-receive-pack) step
defer test.MockVariableValue(&git.DefaultFeatures().SupportProcReceive, false)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
otherRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
readKey, err := deploykey_model.AddDeployKeyToken(t.Context(), repo.ID, "read", perm.AccessModeRead)
require.NoError(t, err)
writeKey, err := deploykey_model.AddDeployKeyToken(t.Context(), repo.ID, "write", perm.AccessModeWrite)
require.NoError(t, err)
requestAs := func(t *testing.T, token, path string, expected int) {
MakeRequest(t, NewRequest(t, "GET", path).AddBasicAuth("deploy-token", token), expected)
}
t.Run("Clone", func(t *testing.T) {
requestAs(t, readKey.Token, "/"+repo.FullName()+"/info/refs?service=git-upload-pack", http.StatusOK)
})
t.Run("PushWithReadToken", func(t *testing.T) {
requestAs(t, readKey.Token, "/"+repo.FullName()+"/info/refs?service=git-receive-pack", http.StatusNotFound)
})
t.Run("PushWithWriteToken", func(t *testing.T) {
requestAs(t, writeKey.Token, "/"+repo.FullName()+"/info/refs?service=git-receive-pack", http.StatusOK)
})
t.Run("OtherRepo", func(t *testing.T) {
requestAs(t, readKey.Token, "/"+otherRepo.FullName()+"/info/refs?service=git-upload-pack", http.StatusNotFound)
})
t.Run("UnknownToken", func(t *testing.T) {
requestAs(t, deploykey_model.DeployTokenPrefix+"0123456789abcdef", "/"+repo.FullName()+"/info/refs?service=git-upload-pack", http.StatusUnauthorized)
})
t.Run("RejectedOutsideGitHTTP", func(t *testing.T) {
// the owner of the repo would be able to read it, the token must not act as that owner
requestAs(t, readKey.Token, "/api/v1/repos/"+repo.FullName(), http.StatusUnauthorized)
})
t.Run("LFS", func(t *testing.T) {
defer test.MockVariableValue(&setting.LFS.StartServer, true)()
batchAs := func(t *testing.T, token, repoName, operation string, expected int) {
req := NewRequestWithJSON(t, "POST", "/"+repoName+"/info/lfs/objects/batch", lfs_module.BatchRequest{Operation: operation}).
AddBasicAuth("deploy-token", token).
SetHeader("Accept", lfs_module.AcceptHeader).
SetHeader("Content-Type", lfs_module.MediaType)
MakeRequest(t, req, expected)
requestAs := func(t *testing.T, token, path string, expected int) {
MakeRequest(t, NewRequest(t, "GET", path).AddBasicAuth("deploy-token", token), expected)
}
batchAs(t, readKey.Token, repo.FullName(), "download", http.StatusOK)
batchAs(t, readKey.Token, repo.FullName(), "upload", http.StatusUnauthorized)
batchAs(t, writeKey.Token, repo.FullName(), "upload", http.StatusOK)
batchAs(t, readKey.Token, otherRepo.FullName(), "download", http.StatusUnauthorized)
t.Run("Clone", func(t *testing.T) {
requestAs(t, readKey.Token, "/"+repo.FullName()+"/info/refs?service=git-upload-pack", http.StatusOK)
})
t.Run("PushWithReadToken", func(t *testing.T) {
pushURL := *u
pushURL.Path = "/" + repo.FullName() + ".git"
pushURL.User = url.UserPassword("deploy-token", readKey.Token)
_, _, err := gitcmd.NewCommand("push").AddDynamicArguments(pushURL.String(), "HEAD:refs/heads/read-token-push").WithRepo(repo).RunStdString(t.Context())
require.Error(t, err)
assert.Contains(t, err.Stderr(), "User permission denied for writing.")
})
t.Run("PushWithWriteToken", func(t *testing.T) {
requestAs(t, writeKey.Token, "/"+repo.FullName()+"/info/refs?service=git-receive-pack", http.StatusOK)
})
t.Run("OtherRepo", func(t *testing.T) {
requestAs(t, readKey.Token, "/"+otherRepo.FullName()+"/info/refs?service=git-upload-pack", http.StatusNotFound)
})
t.Run("UnknownToken", func(t *testing.T) {
requestAs(t, deploykey_model.DeployTokenPrefix+"0123456789abcdef", "/"+repo.FullName()+"/info/refs?service=git-upload-pack", http.StatusUnauthorized)
})
t.Run("RejectedOutsideGitHTTP", func(t *testing.T) {
// the owner of the repo would be able to read it, the token must not act as that owner
requestAs(t, readKey.Token, "/api/v1/repos/"+repo.FullName(), http.StatusUnauthorized)
})
t.Run("LFS", func(t *testing.T) {
defer test.MockVariableValue(&setting.LFS.StartServer, true)()
batchAs := func(t *testing.T, token, repoName, operation string, expected int) {
req := NewRequestWithJSON(t, "POST", "/"+repoName+"/info/lfs/objects/batch", lfs_module.BatchRequest{Operation: operation}).
AddBasicAuth("deploy-token", token).
SetHeader("Accept", lfs_module.AcceptHeader).
SetHeader("Content-Type", lfs_module.MediaType)
MakeRequest(t, req, expected)
}
batchAs(t, readKey.Token, repo.FullName(), "download", http.StatusOK)
batchAs(t, readKey.Token, repo.FullName(), "upload", http.StatusUnauthorized)
batchAs(t, writeKey.Token, repo.FullName(), "upload", http.StatusOK)
batchAs(t, readKey.Token, otherRepo.FullName(), "download", http.StatusUnauthorized)
})
})
}
-5
View File
@@ -814,11 +814,6 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
return func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
// skip this test if git version is low
if !git.DefaultFeatures().SupportProcReceive {
return
}
gitRepo, err := git.OpenRepositoryLocal(t.Context(), dstPath)
require.NoError(t, err)
@@ -169,12 +169,7 @@ func doGitCloneFail(u *url.URL) func(*testing.T) {
func doGitInitTestRepository(dstPath string) func(*testing.T) {
return func(t *testing.T) {
// Init repository in dstPath
assert.NoError(t, git.InitRepositoryLocal(t.Context(), dstPath, false, git.Sha1ObjectFormat.Name()))
// forcibly set default branch to master
_, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+"master").
WithDir(dstPath).
RunStdString(t.Context())
assert.NoError(t, err)
assert.NoError(t, git.InitRepositoryLocal(t.Context(), dstPath, false, git.Sha1ObjectFormat.Name(), "master"))
assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "README.md"), []byte("# Testing Repository\n\nOriginally created in: "+dstPath), 0o644))
assert.NoError(t, gitAddChangesDeprecated(t.Context(), dstPath, true))
signature := git.Signature{
+1
View File
@@ -98,6 +98,7 @@ func testLinksNoLogin(t *testing.T) {
assertLinkPageComplete(t, nil, link)
}
MakeRequest(t, NewRequest(t, "GET", "/.well-known/security.txt"), http.StatusOK)
MakeRequest(t, NewRequest(t, "GET", "/ssh_info"), http.StatusOK)
}
func testLinksRedirectsNoLogin(t *testing.T) {
-5
View File
@@ -40,11 +40,6 @@ func TestRepoWikiPages(t *testing.T) {
}
func testRepoWikiCloneHTTP(t *testing.T, u *url.URL) {
// When proc-receive support is enabled globally, the HTTP receive-pack pre-check
// must still require write access for wiki repositories. Exercise this with a
// normal wiki push because the regression is about the pre-check, not agit refs.
require.True(t, git.DefaultFeatures().SupportProcReceive) // modern git should all support proc-receive
wikiURL := *u
wikiURL.Path = "/user2/repo1.wiki.git"