Fix verifyCommits error when push a new branch (#26664)
> ### 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: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
@ -28,23 +28,31 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
|
||||
_ = stdoutWriter.Close()
|
||||
}()
|
||||
|
||||
var command *git.Command
|
||||
if oldCommitID == git.EmptySHA {
|
||||
// When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all":
|
||||
// List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits
|
||||
// So, it only lists the new commits received, doesn't list the commits already present in the receiving repository
|
||||
command = git.NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(newCommitID).AddArguments("--not", "--all")
|
||||
} else {
|
||||
command = git.NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID)
|
||||
}
|
||||
// This is safe as force pushes are already forbidden
|
||||
err = git.NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID).
|
||||
Run(&git.RunOpts{
|
||||
Env: env,
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
|
||||
_ = stdoutWriter.Close()
|
||||
err := readAndVerifyCommitsFromShaReader(stdoutReader, repo, env)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
cancel()
|
||||
}
|
||||
_ = stdoutReader.Close()
|
||||
return err
|
||||
},
|
||||
})
|
||||
err = command.Run(&git.RunOpts{
|
||||
Env: env,
|
||||
Dir: repo.Path,
|
||||
Stdout: stdoutWriter,
|
||||
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
|
||||
_ = stdoutWriter.Close()
|
||||
err := readAndVerifyCommitsFromShaReader(stdoutReader, repo, env)
|
||||
if err != nil {
|
||||
log.Error("%v", err)
|
||||
cancel()
|
||||
}
|
||||
_ = stdoutReader.Close()
|
||||
return err
|
||||
},
|
||||
})
|
||||
if err != nil && !isErrUnverifiedCommit(err) {
|
||||
log.Error("Unable to check commits from %s to %s in %s: %v", oldCommitID, newCommitID, repo.Path, err)
|
||||
}
|
||||
|
43
routers/private/hook_verification_test.go
Normal file
43
routers/private/hook_verification_test.go
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package private
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testReposDir = "tests/repos/"
|
||||
|
||||
func TestVerifyCommits(t *testing.T) {
|
||||
unittest.PrepareTestEnv(t)
|
||||
|
||||
gitRepo, err := git.OpenRepository(context.Background(), testReposDir+"repo1_hook_verification")
|
||||
defer gitRepo.Close()
|
||||
assert.NoError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
base, head string
|
||||
verified bool
|
||||
}{
|
||||
{"72920278f2f999e3005801e5d5b8ab8139d3641c", "d766f2917716d45be24bfa968b8409544941be32", true},
|
||||
{git.EmptySHA, "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
|
||||
{"9779d17a04f1e2640583d35703c62460b2d86e0a", "72920278f2f999e3005801e5d5b8ab8139d3641c", false},
|
||||
{git.EmptySHA, "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
err = verifyCommits(tc.base, tc.head, gitRepo, nil)
|
||||
if tc.verified {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
}
|
||||
}
|
17
routers/private/main_test.go
Normal file
17
routers/private/main_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package private
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
})
|
||||
}
|
1
routers/private/tests/repos/repo1_hook_verification/HEAD
Normal file
1
routers/private/tests/repos/repo1_hook_verification/HEAD
Normal file
@ -0,0 +1 @@
|
||||
ref: refs/heads/main
|
@ -0,0 +1,6 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = false
|
||||
bare = true
|
||||
symlinks = false
|
||||
ignorecase = true
|
@ -0,0 +1 @@
|
||||
d766f2917716d45be24bfa968b8409544941be32 refs/heads/main
|
@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 d766f2917716d45be24bfa968b8409544941be32 Gitea <gitea@fake.local> 1693148474 +0800 push
|
@ -0,0 +1 @@
|
||||
0000000000000000000000000000000000000000 d766f2917716d45be24bfa968b8409544941be32 Gitea <gitea@fake.local> 1693148474 +0800 push
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
x<01><>K
|
||||
1]<5D><14><0B><><EFBFBD>A<EFBFBD>S<EFBFBD><53>$<1D>"32oo<6F><06><>W<EFBFBD><57><EFBFBD><EFBFBD>{<7B>!<21><>`<60><>JC%<25>.<2E>$<07>r]sѱe$<24>m<EFBFBD><6D>M<EFBFBD><4D>)<29><><EFBFBD>(O`<60>btl<>E[:;4<12><>H<>1_<31><5F><EFBFBD>ray<61><79><EFBFBD>l<EFBFBD><6C><EFBFBD><EFBFBD>~<7E><>E<EFBFBD>L@c<><02>Xv<58>M<EFBFBD><4D>":<3A>MۃG<DB83>_}<7D>?<3F>
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
x<01><>1
|
||||
!ES{<7B><>AwGGa 9E<39>QgW<10><><EFBFBD>#<23>A<EFBFBD><0F><><EFBFBD><EFBFBD>Z<18>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>p<EFBFBD><70>(<28>(<28><><EFBFBD><EFBFBD>Bh<42>ۼ&<26><11><14><><EFBFBD>:pLY`<60><><EFBFBD>U<EFBFBD><55>-<2D>z<EFBFBD><7A><EFBFBD><1A><>\<5C><>ZM:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>xJ/<2F>G}:<3A>3
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
x<01><>A
|
||||
<EFBFBD>0E]<5D><14>$<24>L<EFBFBD><0C>x<EFBFBD>L2<4C>]<5D><><EFBFBD>
|
||||
<EFBFBD><EFBFBD><EFBFBD>
|
@ -0,0 +1,3 @@
|
||||
x<01><>ˮ<EFBFBD>FE3<45>+zn%44<34>!%Qx<51><78>ۀs<>A<EFBFBD>`8<><38><EFBFBD><EFBFBD>{<7B><>2IM<49>j<EFBFBD><6A><EFBFBD><EFBFBD><EFBFBD>d<EFBFBD><64>f<06><><EFBFBD>2<EFBFBD><32><EFBFBD>"<22>$<24>e<EFBFBD><65>
|
||||
-(<28> <20><04>!<21><>J"<22>a<EFBFBD><17>@<40>Ba<42><61>Ho3<6F><33>V<EFBFBD><56><04><$<24>/)<29>$J<>JD<04>B<EFBFBD><42>H<EFBFBD><1F><><EFBFBD>{<7B>#<23>RR<52><52>O<EFBFBD><4F>nf<6E><66>F<EFBFBD><46>O<EFBFBD><4F>
|
||||
<EFBFBD>q[<5B><>2<EFBFBD>̇~<7E><><EFBFBD><EFBFBD><7F><EFBFBD>zjj<6A><6A><EFBFBD><EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD>}prm<72>Fqh<71><68>`@ث<><D8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>f<D598>?3<>[7<><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) ^<5E><>u<EFBFBD>ֿ,<2C><><EFBFBD>l7<6C>z<EFBFBD><06>r|&<10>Ou4<75><34>9<EFBFBD>:<3A><>Qj<51><6A><EFBFBD><15><>1x<31><78><EFBFBD>6<EFBFBD>Q<EFBFBD><51><EFBFBD><EFBFBD>%<25><>t<><74>s<EFBFBD><73><EFBFBD>V<EFBFBD>|(<1C>V<EFBFBD><56>,aL,<2C><>G~<7E><><16><><EFBFBD><EFBFBD><EFBFBD>r<1D><><EFBFBD><EFBFBD>@<40>`<60><><EFBFBD>$[! Xˊep<><70><1E>[8 o<><6F>(<28><><EFBFBD>k<EFBFBD>Z<EFBFBD>γy<CEB3>eй<65><D0B9><EFBFBD><05>Y<EFBFBD><59>k<EFBFBD>d<64><7F>6<EFBFBD>3<EFBFBD>;3<><06> R<>iދdY<64>Dk91V]/C<>#<23><>&<26><>po<70>F<EFBFBD>b<EFBFBD><62><EFBFBD>}<7D><><EFBFBD><EFBFBD><EFBFBD>uW&]+m xaqd<71>I<EFBFBD>X<EFBFBD><58>3
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
||||
|
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user