Skip to content

Commit 93c36f3

Browse files
GiteaBotCaiCandongwxiaoguanglunny
authored
Fix verifyCommits error when push a new branch (#26664) (#26810)
Backport #26664 by @CaiCandong > ### Description > If a new branch is pushed, and the repository has a rule that would require signed commits for the new branch, the commit is rejected with a 500 error regardless of whether it's signed. > > When pushing a new branch, the "old" commit is the empty ID (0000000000000000000000000000000000000000). verifyCommits has no provision for this and passes an invalid commit range to git rev-list. Prior to 1.19 this wasn't an issue because only pre-existing individual branches could be protected. > > I was able to reproduce with [try.gitea.io/CraigTest/test](https://try.gitea.io/CraigTest/test), which is set up with a blanket rule to require commits on all branches. Fix #25565 Very thanks to @Craig-Holmquist-NTI for reporting the bug and suggesting an valid solution! Co-authored-by: CaiCandong <[email protected]> Co-authored-by: wxiaoguang <[email protected]> Co-authored-by: Lunny Xiao <[email protected]>
1 parent 302c03c commit 93c36f3

File tree

43 files changed

+270
-20
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+270
-20
lines changed

models/fixtures/email_address.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,4 +276,12 @@
276276
277277
lower_email: [email protected]
278278
is_activated: false
279-
is_primary: false
279+
is_primary: false
280+
281+
-
282+
id: 36
283+
uid: 36
284+
285+
lower_email: [email protected]
286+
is_activated: true
287+
is_primary: false

models/fixtures/gpg_key.yml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,23 @@
1-
[] # empty
1+
-
2+
id: 5
3+
owner_id: 36
4+
key_id: B15431642629B826
5+
primary_key_id:
6+
content: xsDNBGTrY3UBDAC2HLBqmMplAV15qSnC7g1c4dV406f5EHNhFr95Nup2My6b2eafTlvedv77s8PT/I7F3fy4apOZs5A7w2SsPlLMcQ3ev4uGOsxRtkq5RLy1Yb6SNueX0Da2UVKR5KTC5Q6BWaqxwS0IjKOLZ/xz0Pbe/ClV3bZSKBEY2omkVo3Z0HZ771vB2clPRvGJ/IdeKOsZ3ZytSFXfyiJBdARmeSPmydXLil8+Ibq5iLAeow5PK8hK1TCOnKHzLWNqcNq70tyjoHvcGi70iGjoVEEUgPCLLuU8WmzTJwlvA3BuDzjtaO7TLo/jdE6iqkHtMSS8x+43sAH6hcFRCWAVh/0Uq7n36uGDfNxGnX3YrmX3LR9x5IsBES1rGGWbpxio4o5GIf/Xd+JgDd9rzJCqRuZ3/sW/TxK38htWaVNZV0kMkHUCTc1ctzWpCm635hbFCHBhPYIp+/z206khkAKDbz/CNuU91Wazsh7KO07wrwDtxfDDbInJ8TfHE2TGjzjQzgChfmcAEQEAAQ==
7+
verified: true
8+
can_sign: true
9+
can_encrypt_comms: true
10+
can_encrypt_storage: true
11+
can_certify: true
12+
13+
-
14+
id: 6
15+
owner_id: 36
16+
key_id: EE3AF48454AFD619
17+
primary_key_id: B15431642629B826
18+
content: zsDNBGTrY3UBDADsHrzuOicQaPdUQm0+0UNrs92cESm/j/4yBBUk+sfLZAo6J99c4eh4nAQzzZ7al080rYKB0G+7xoRz1eHcQH6zrVcqB8KYtf/sdY47WaMiMyxM+kTSvzp7tsv7QuSQZ0neUEXRyYMz5ttBfIjWUd+3NDItuHyB+MtNWlS3zXgaUbe5VifqKaNmzN0Ye4yXTKcpypE3AOqPVz+iIFv3c6TmsqLHJaR4VoicCleAqLyF/28WsJO7M9dDW+EM3MZVnsVpycTURyHAJGfSk10waQZAaRwmarCN/q0KEJ+aEAK/SRliUneBZoMO5hY5iBeG432tofwaQqAahPv9uXIb1n2JEMKwnMlMA9UGD1AcDbywfj1m/ZGBBw95i4Ekkfn43RvV3THr7uJU/dRqqP+iic4MwpUrOxqELW/kmeHXlBcNbZZhEEvwRoW7U2/9eeuog4nRleRJ0pi/xOP9wmxkKjaIPIK3phdBtEpVk4w/UTAWNdyIIrFggukeAnZFyGJwlm8AEQEAAQ==
19+
verified: true
20+
can_sign: true
21+
can_encrypt_comms: true
22+
can_encrypt_storage: true
23+
can_certify: true

models/fixtures/user.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@
13011301
lower_name: limited_org36
13021302
name: limited_org36
13031303
full_name: Limited Org 36
1304-
email: limited_org36@example.com
1304+
email: abcde@gitea.com
13051305
keep_email_private: false
13061306
email_notifications_preference: enabled
13071307
passwd: ZogKvWdyEx:password
@@ -1320,7 +1320,7 @@
13201320
allow_create_organization: true
13211321
prohibit_login: false
13221322
avatar: avatar22
1323-
avatar_email: limited_org36@example.com
1323+
avatar_email: abcde@gitea.com
13241324
use_custom_avatar: false
13251325
num_followers: 0
13261326
num_following: 0

routers/private/hook_verification.go

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,31 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
2828
_ = stdoutWriter.Close()
2929
}()
3030

31+
var command *git.Command
32+
if oldCommitID == git.EmptySHA {
33+
// When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all":
34+
// List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits
35+
// So, it only lists the new commits received, doesn't list the commits already present in the receiving repository
36+
command = git.NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(newCommitID).AddArguments("--not", "--all")
37+
} else {
38+
command = git.NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID)
39+
}
3140
// This is safe as force pushes are already forbidden
32-
err = git.NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID).
33-
Run(&git.RunOpts{
34-
Env: env,
35-
Dir: repo.Path,
36-
Stdout: stdoutWriter,
37-
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
38-
_ = stdoutWriter.Close()
39-
err := readAndVerifyCommitsFromShaReader(stdoutReader, repo, env)
40-
if err != nil {
41-
log.Error("%v", err)
42-
cancel()
43-
}
44-
_ = stdoutReader.Close()
45-
return err
46-
},
47-
})
41+
err = command.Run(&git.RunOpts{
42+
Env: env,
43+
Dir: repo.Path,
44+
Stdout: stdoutWriter,
45+
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
46+
_ = stdoutWriter.Close()
47+
err := readAndVerifyCommitsFromShaReader(stdoutReader, repo, env)
48+
if err != nil {
49+
log.Error("%v", err)
50+
cancel()
51+
}
52+
_ = stdoutReader.Close()
53+
return err
54+
},
55+
})
4856
if err != nil && !isErrUnverifiedCommit(err) {
4957
log.Error("Unable to check commits from %s to %s in %s: %v", oldCommitID, newCommitID, repo.Path, err)
5058
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package private
5+
6+
import (
7+
"context"
8+
"testing"
9+
10+
"code.gitea.io/gitea/models/unittest"
11+
"code.gitea.io/gitea/modules/git"
12+
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
var testReposDir = "tests/repos/"
17+
18+
func TestVerifyCommits(t *testing.T) {
19+
unittest.PrepareTestEnv(t)
20+
21+
gitRepo, err := git.OpenRepository(context.Background(), testReposDir+"repo1_hook_verification")
22+
defer gitRepo.Close()
23+
assert.NoError(t, err)
24+
25+
testCases := []struct {
26+
base, head string
27+
verified bool
28+
}{
29+
{"72920278f2f999e3005801e5d5b8ab8139d3641c", "d766f2917716d45be24bfa968b8409544941be32", true},
30+
{git.EmptySHA, "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
31+
{"9779d17a04f1e2640583d35703c62460b2d86e0a", "72920278f2f999e3005801e5d5b8ab8139d3641c", false},
32+
{git.EmptySHA, "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
33+
}
34+
35+
for _, tc := range testCases {
36+
err = verifyCommits(tc.base, tc.head, gitRepo, nil)
37+
if tc.verified {
38+
assert.NoError(t, err)
39+
} else {
40+
assert.Error(t, err)
41+
}
42+
}
43+
}

routers/private/main_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2017 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package private
5+
6+
import (
7+
"path/filepath"
8+
"testing"
9+
10+
"code.gitea.io/gitea/models/unittest"
11+
)
12+
13+
func TestMain(m *testing.M) {
14+
unittest.MainTest(m, &unittest.TestOptions{
15+
GiteaRootPath: filepath.Join("..", ".."),
16+
})
17+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ref: refs/heads/main
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[core]
2+
repositoryformatversion = 0
3+
filemode = false
4+
bare = true
5+
symlinks = false
6+
ignorecase = true
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
d766f2917716d45be24bfa968b8409544941be32 refs/heads/main
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0000000000000000000000000000000000000000 d766f2917716d45be24bfa968b8409544941be32 Gitea <[email protected]> 1693148474 +0800 push

0 commit comments

Comments
 (0)