Skip to content

Commit 93c36f3

Browse files
GiteaBotCaiCandongwxiaoguanglunny
authored
Fix verifyCommits error when push a new branch (go-gitea#26664) (go-gitea#26810)
Backport go-gitea#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 go-gitea#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
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
x��K
2+
1]�� ���A�S��$�"32 oo���W���{�!��`��JC%�.� $�r]sѱe$�m��M��)���(O`�btl�E[:;4��H�1_���ray���l���~��E�L@c��Xv�M��":�MۃG�_}�?�
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
x��1
2+
!ES{��AwGGa 9E�Qg W���#�A�����Z�/������p��(�(���Bh�ۼ&�����:pLY`���U��-�z����\��ZM:��������xJ/�G}:�3

routers/private/tests/repos/repo1_hook_verification/objects/cb/a4c30c196a0e03e7bdf6eeb8393d14b9d073aa

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
x��A
2+
�0E]��$�L� �x�L2�]���
3+
���\}����e[��:{�M���Z5b�8$���v ��f�R�37];�ˆ�bt�� ��3�$�,tX��G��>m���p���1w͗�-7p���Ąp��Zs�DZ�L̾������L��e@�

routers/private/tests/repos/repo1_hook_verification/objects/d7/66f2917716d45be24bfa968b8409544941be32

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
x��ˮ�FE3�+zn%44�!%Qx��ۀs�A�` 8����{��2IM�j�����d��f���2���"�$�e��
2+
-(� ��!��J"�a��@�Ba��Ho3��V���<$�/)�$J�JD�B��H����{� #� RR��O��nf��F��O��
3+
�q[��2�̇~������zjj���L����}prm�Fqh�� `@ث������՘f�?3�[7�����) ^��u�ֿ,���l7�z��r|&�Ou4��9�:��Qj�����1x���6�Q����%��t��s��V�| (�V��,aL,��G~�������r����@�`���$[! Xˊep���[8 o��(���k�Z�γy�eй����Y��k�d��6�3�;3�� R�i ދdY�Dk91V]/C�#��&��po�F�b���}�����uW&]+m xaqd�I�X��3��3���K���I#�i_�rg�������ĩ7�=�`@[��&A��̤�L�o��3~M����8MGt���>��x��vQ�(��a��W�o"��s�r�z��e�ŭ}�QD��֨fK)�m�r>>�������̚$�F8�x���^J� k{mcz�I*�^�Mb�� m�6��M~h�p��{���0��� ]€?nUwg�ɠ���J �б��<�7�2
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

routers/private/tests/repos/repo1_hook_verification/objects/tmp_objdir-incoming-a21648/cb/a4c30c196a0e03e7bdf6eeb8393d14b9d073aa

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
x��A
2+
�0E]��$�L� �x�L2�]���
3+
���\}����e[��:{�M���Z5b�8$���v ��f�R�37];�ˆ�bt�� ��3�$�,tX��G��>m���p���1w͗�-7p���Ąp��Zs�DZ�L̾������L��e@�
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
d766f2917716d45be24bfa968b8409544941be32
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# GPG key for [email protected]
2+
3+
-----BEGIN PGP PUBLIC KEY BLOCK-----
4+
5+
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
41+
4akc
42+
=OYIo
43+
-----END PGP PUBLIC KEY BLOCK-----
44+
45+
-----BEGIN PGP PRIVATE KEY BLOCK-----
46+
47+
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
125+
ZZtqph2TItCeV04HoaKHHc254akc
126+
=PPG4
127+
-----END PGP PRIVATE KEY BLOCK-----

0 commit comments

Comments
 (0)