diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-05-24 10:10:18 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-05-24 10:10:18 +0300 |
commit | 392aa116d7071376e8f30fccf78984b3016fa159 (patch) | |
tree | 097702ab96ac1c0f3ad309e6e9123e56d994396c | |
parent | bf4966c6f1c3cc9c89a267cf8a1a3d94b944e49e (diff) | |
parent | ab1e3d7ecdcde5a1be5dea429cea2141463f1e60 (diff) |
Merge branch 'pks-gitaly-gitconfig-clean' into pks-ci-fail-on-gitconfig-readspks-ci-fail-on-gitconfig-reads
-rw-r--r-- | cmd/gitaly-git2go-v15/cherry_pick_test.go | 58 | ||||
-rw-r--r-- | cmd/gitaly-git2go-v15/conflicts_test.go | 101 | ||||
-rw-r--r-- | cmd/gitaly-git2go-v15/main.go | 10 | ||||
-rw-r--r-- | cmd/gitaly-git2go-v15/merge_test.go | 218 | ||||
-rw-r--r-- | cmd/gitaly-git2go-v15/rebase_test.go | 11 | ||||
-rw-r--r-- | cmd/gitaly-git2go-v15/revert_test.go | 94 | ||||
-rw-r--r-- | cmd/gitaly-git2go-v15/testhelper/testhelper.go | 48 | ||||
-rw-r--r-- | cmd/gitaly-git2go-v15/testhelper_test.go | 27 | ||||
-rw-r--r-- | internal/command/command.go | 36 | ||||
-rw-r--r-- | internal/git/command_factory.go | 30 | ||||
-rw-r--r-- | internal/git/command_factory_test.go | 21 | ||||
-rw-r--r-- | internal/git/gittest/command.go | 1 | ||||
-rw-r--r-- | internal/git2go/executor.go | 1 | ||||
-rw-r--r-- | internal/gitaly/rubyserver/rubyserver.go | 1 | ||||
-rw-r--r-- | internal/testhelper/testcfg/build.go | 13 | ||||
-rwxr-xr-x | ruby/bin/gitaly-ruby | 2 | ||||
-rw-r--r-- | ruby/spec/spec_helper.rb | 6 |
17 files changed, 347 insertions, 331 deletions
diff --git a/cmd/gitaly-git2go-v15/cherry_pick_test.go b/cmd/gitaly-git2go-v15/cherry_pick_test.go index 5902d1fdf..4e4478317 100644 --- a/cmd/gitaly-git2go-v15/cherry_pick_test.go +++ b/cmd/gitaly-git2go-v15/cherry_pick_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil" - cmdtesthelper "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/testhelper" + "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v15/internal/git2go" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg" @@ -81,9 +81,9 @@ func TestCherryPick_validation(t *testing.T) { func TestCherryPick(t *testing.T) { testcases := []struct { desc string - base map[string]string - ours map[string]string - commit map[string]string + base []gittest.TreeEntry + ours []gittest.TreeEntry + commit []gittest.TreeEntry expected map[string]string expectedCommitID string expectedErr error @@ -91,44 +91,44 @@ func TestCherryPick(t *testing.T) { }{ { desc: "trivial cherry-pick succeeds", - base: map[string]string{ - "file": "foo", + base: []gittest.TreeEntry{ + {Path: "file", Content: "foo", Mode: "100644"}, }, - ours: map[string]string{ - "file": "foo", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "foo", Mode: "100644"}, }, - commit: map[string]string{ - "file": "foobar", + commit: []gittest.TreeEntry{ + {Path: "file", Content: "foobar", Mode: "100644"}, }, expected: map[string]string{ "file": "foobar", }, - expectedCommitID: "aa3c9f5ad67ad86e313129a851f6d64614be7f6e", + expectedCommitID: "a54ea83118c363c34cc605a6e61fd7abc4795cc4", }, { desc: "conflicting cherry-pick fails", - base: map[string]string{ - "file": "foo", + base: []gittest.TreeEntry{ + {Path: "file", Content: "foo", Mode: "100644"}, }, - ours: map[string]string{ - "file": "fooqux", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "fooqux", Mode: "100644"}, }, - commit: map[string]string{ - "file": "foobar", + commit: []gittest.TreeEntry{ + {Path: "file", Content: "foobar", Mode: "100644"}, }, expectedErr: git2go.HasConflictsError{}, expectedErrMsg: "cherry-pick: could not apply due to conflicts", }, { desc: "empty cherry-pick fails", - base: map[string]string{ - "file": "foo", + base: []gittest.TreeEntry{ + {Path: "file", Content: "foo", Mode: "100644"}, }, - ours: map[string]string{ - "file": "fooqux", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "fooqux", Mode: "100644"}, }, - commit: map[string]string{ - "file": "fooqux", + commit: []gittest.TreeEntry{ + {Path: "file", Content: "fooqux", Mode: "100644"}, }, expectedErr: git2go.EmptyError{}, expectedErrMsg: "cherry-pick: could not apply because the result was empty", @@ -139,8 +139,8 @@ func TestCherryPick(t *testing.T) { }, { desc: "fails on nonexistent cherry-pick commit", - ours: map[string]string{ - "file": "fooqux", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "fooqux", Mode: "100644"}, }, expectedErrMsg: "cherry-pick: commit lookup: lookup commit \"nonexistent\": revspec 'nonexistent' not found", }, @@ -150,14 +150,14 @@ func TestCherryPick(t *testing.T) { testcfg.BuildGitalyGit2Go(t, cfg) executor := buildExecutor(t, cfg) - base := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{nil}, tc.base) + base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries(tc.base...)) ours, commit := "nonexistent", "nonexistent" if len(tc.ours) > 0 { - ours = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.ours).String() + ours = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.ours...)).String() } if len(tc.commit) > 0 { - commit = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.commit).String() + commit = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.commit...)).String() } t.Run(tc.desc, func(t *testing.T) { @@ -200,7 +200,7 @@ func TestCherryPick(t *testing.T) { commit, err := repo.LookupCommit(commitOid) require.NoError(t, err) - require.Equal(t, &cmdtesthelper.DefaultAuthor, commit.Author()) + require.Equal(t, &DefaultAuthor, commit.Author()) require.Equal(t, &committer, commit.Committer()) tree, err := commit.Tree() diff --git a/cmd/gitaly-git2go-v15/conflicts_test.go b/cmd/gitaly-git2go-v15/conflicts_test.go index 6fa843aa6..4551ceb7c 100644 --- a/cmd/gitaly-git2go-v15/conflicts_test.go +++ b/cmd/gitaly-git2go-v15/conflicts_test.go @@ -7,10 +7,9 @@ import ( "fmt" "testing" - git "github.com/libgit2/git2go/v33" "github.com/stretchr/testify/require" - cmdtesthelper "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/testhelper" glgit "gitlab.com/gitlab-org/gitaly/v15/internal/git" + "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v15/internal/git2go" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg" @@ -21,34 +20,34 @@ import ( func TestConflicts(t *testing.T) { testcases := []struct { desc string - base map[string]string - ours map[string]string - theirs map[string]string + base []gittest.TreeEntry + ours []gittest.TreeEntry + theirs []gittest.TreeEntry conflicts []git2go.Conflict }{ { desc: "no conflicts", - base: map[string]string{ - "file": "a", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - ours: map[string]string{ - "file": "a", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - theirs: map[string]string{ - "file": "b", + theirs: []gittest.TreeEntry{ + {Path: "file", Content: "b", Mode: "100644"}, }, conflicts: nil, }, { desc: "single file", - base: map[string]string{ - "file": "a", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - ours: map[string]string{ - "file": "b", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "b", Mode: "100644"}, }, - theirs: map[string]string{ - "file": "c", + theirs: []gittest.TreeEntry{ + {Path: "file", Content: "c", Mode: "100644"}, }, conflicts: []git2go.Conflict{ { @@ -61,17 +60,17 @@ func TestConflicts(t *testing.T) { }, { desc: "multiple files with single conflict", - base: map[string]string{ - "file-1": "a", - "file-2": "a", + base: []gittest.TreeEntry{ + {Path: "file-1", Content: "a", Mode: "100644"}, + {Path: "file-2", Content: "a", Mode: "100644"}, }, - ours: map[string]string{ - "file-1": "b", - "file-2": "b", + ours: []gittest.TreeEntry{ + {Path: "file-1", Content: "b", Mode: "100644"}, + {Path: "file-2", Content: "b", Mode: "100644"}, }, - theirs: map[string]string{ - "file-1": "a", - "file-2": "c", + theirs: []gittest.TreeEntry{ + {Path: "file-1", Content: "a", Mode: "100644"}, + {Path: "file-2", Content: "c", Mode: "100644"}, }, conflicts: []git2go.Conflict{ { @@ -84,17 +83,17 @@ func TestConflicts(t *testing.T) { }, { desc: "multiple conflicts", - base: map[string]string{ - "file-1": "a", - "file-2": "a", + base: []gittest.TreeEntry{ + {Path: "file-1", Content: "a", Mode: "100644"}, + {Path: "file-2", Content: "a", Mode: "100644"}, }, - ours: map[string]string{ - "file-1": "b", - "file-2": "b", + ours: []gittest.TreeEntry{ + {Path: "file-1", Content: "b", Mode: "100644"}, + {Path: "file-2", Content: "b", Mode: "100644"}, }, - theirs: map[string]string{ - "file-1": "c", - "file-2": "c", + theirs: []gittest.TreeEntry{ + {Path: "file-1", Content: "c", Mode: "100644"}, + {Path: "file-2", Content: "c", Mode: "100644"}, }, conflicts: []git2go.Conflict{ { @@ -113,14 +112,14 @@ func TestConflicts(t *testing.T) { }, { desc: "modified-delete-conflict", - base: map[string]string{ - "file": "content", + base: []gittest.TreeEntry{ + {Path: "file", Content: "content", Mode: "100644"}, }, - ours: map[string]string{ - "file": "changed", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "changed", Mode: "100644"}, }, - theirs: map[string]string{ - "different-file": "unrelated", + theirs: []gittest.TreeEntry{ + {Path: "different-file", Content: "unrelated", Mode: "100644"}, }, conflicts: []git2go.Conflict{ { @@ -136,14 +135,14 @@ func TestConflicts(t *testing.T) { // detection and so don't we. The rename conflict is // thus split up into three conflicts. desc: "rename-rename-conflict", - base: map[string]string{ - "file": "a\nb\nc\nd\ne\nf\ng\n", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a\nb\nc\nd\ne\nf\ng\n", Mode: "100644"}, }, - ours: map[string]string{ - "renamed-1": "a\nb\nc\nd\ne\nf\ng\n", + ours: []gittest.TreeEntry{ + {Path: "renamed-1", Content: "a\nb\nc\nd\ne\nf\ng\n", Mode: "100644"}, }, - theirs: map[string]string{ - "renamed-2": "a\nb\nc\nd\ne\nf\ng\n", + theirs: []gittest.TreeEntry{ + {Path: "renamed-2", Content: "a\nb\nc\nd\ne\nf\ng\n", Mode: "100644"}, }, conflicts: []git2go.Conflict{ { @@ -174,9 +173,9 @@ func TestConflicts(t *testing.T) { testcfg.BuildGitalyGit2Go(t, cfg) - base := cmdtesthelper.BuildCommit(t, repoPath, nil, tc.base) - ours := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.ours) - theirs := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.theirs) + base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries(tc.base...)) + ours := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.ours...)) + theirs := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.theirs...)) t.Run(tc.desc, func(t *testing.T) { ctx := testhelper.Context(t) @@ -195,7 +194,7 @@ func TestConflicts(t *testing.T) { func TestConflicts_checkError(t *testing.T) { cfg, repo, repoPath := testcfg.BuildWithRepo(t) - base := cmdtesthelper.BuildCommit(t, repoPath, nil, nil) + base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries()) validOID := glgit.ObjectID(base.String()) executor := buildExecutor(t, cfg) diff --git a/cmd/gitaly-git2go-v15/main.go b/cmd/gitaly-git2go-v15/main.go index dc3516af2..e4a51354e 100644 --- a/cmd/gitaly-git2go-v15/main.go +++ b/cmd/gitaly-git2go-v15/main.go @@ -102,6 +102,16 @@ func main() { fatalf(logger, encoder, "enable fsync: %s", err) } + for _, configLevel := range []git.ConfigLevel{ + git.ConfigLevelSystem, + git.ConfigLevelXDG, + git.ConfigLevelGlobal, + } { + if err := git.SetSearchPath(configLevel, "/dev/null"); err != nil { + fatalf(logger, encoder, "setting search path: %s", err) + } + } + subcmdLogger := logger.WithField("command.subcommand", subcmdFlags.Name()) subcmdLogger.Infof("starting %s command", subcmdFlags.Name()) diff --git a/cmd/gitaly-git2go-v15/merge_test.go b/cmd/gitaly-git2go-v15/merge_test.go index 68d36b9f7..8f1b79968 100644 --- a/cmd/gitaly-git2go-v15/merge_test.go +++ b/cmd/gitaly-git2go-v15/merge_test.go @@ -8,11 +8,11 @@ import ( "testing" "time" - git "github.com/libgit2/git2go/v33" + libgit2 "github.com/libgit2/git2go/v33" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil" - cmdtesthelper "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/testhelper" + "gitlab.com/gitlab-org/gitaly/v15/internal/git" "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v15/internal/git2go" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" @@ -113,9 +113,9 @@ func TestMerge_trees(t *testing.T) { testcases := []struct { desc string - base map[string]string - ours map[string]string - theirs map[string]string + base []gittest.TreeEntry + ours []gittest.TreeEntry + theirs []gittest.TreeEntry expected map[string]string withCommitter bool squash bool @@ -124,113 +124,113 @@ func TestMerge_trees(t *testing.T) { }{ { desc: "trivial merge succeeds", - base: map[string]string{ - "file": "a", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - ours: map[string]string{ - "file": "a", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - theirs: map[string]string{ - "file": "a", + theirs: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, expected: map[string]string{ "file": "a", }, expectedResponse: git2go.MergeResult{ - CommitID: "7d5ae8fb6d2b301c53560bd728004d77778998df", + CommitID: "0db317551c49eddadde2b337550d8e57d9536886", }, }, { desc: "trivial merge with different committer succeeds", - base: map[string]string{ - "file": "a", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - ours: map[string]string{ - "file": "a", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - theirs: map[string]string{ - "file": "a", + theirs: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, expected: map[string]string{ "file": "a", }, withCommitter: true, expectedResponse: git2go.MergeResult{ - CommitID: "cba8c5ddf5a5a24f2f606e4b62d348feb1214b70", + CommitID: "38dcbe72d91ed5621286290f70df9a5dd08f5cb6", }, }, { desc: "trivial squash succeeds", - base: map[string]string{ - "file": "a", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - ours: map[string]string{ - "file": "a", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, - theirs: map[string]string{ - "file": "a", + theirs: []gittest.TreeEntry{ + {Path: "file", Content: "a", Mode: "100644"}, }, expected: map[string]string{ "file": "a", }, squash: true, expectedResponse: git2go.MergeResult{ - CommitID: "d4c52f063cd6544959d6b0d9a3d8fa8463c34086", + CommitID: "a0781480ce3cbba80440e6c112c5ee7f718ed3c2", }, }, { desc: "non-trivial merge succeeds", - base: map[string]string{ - "file": "a\nb\nc\nd\ne\nf\n", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a\nb\nc\nd\ne\nf\n", Mode: "100644"}, }, - ours: map[string]string{ - "file": "0\na\nb\nc\nd\ne\nf\n", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "0\na\nb\nc\nd\ne\nf\n", Mode: "100644"}, }, - theirs: map[string]string{ - "file": "a\nb\nc\nd\ne\nf\n0\n", + theirs: []gittest.TreeEntry{ + {Path: "file", Content: "a\nb\nc\nd\ne\nf\n0\n", Mode: "100644"}, }, expected: map[string]string{ "file": "0\na\nb\nc\nd\ne\nf\n0\n", }, expectedResponse: git2go.MergeResult{ - CommitID: "348b9b489c3ca128a4555c7a51b20335262519c7", + CommitID: "3c030d1ee80bbb005666619375fa0629c86b9534", }, }, { desc: "non-trivial squash succeeds", - base: map[string]string{ - "file": "a\nb\nc\nd\ne\nf\n", + base: []gittest.TreeEntry{ + {Path: "file", Content: "a\nb\nc\nd\ne\nf\n", Mode: "100644"}, }, - ours: map[string]string{ - "file": "0\na\nb\nc\nd\ne\nf\n", + ours: []gittest.TreeEntry{ + {Path: "file", Content: "0\na\nb\nc\nd\ne\nf\n", Mode: "100644"}, }, - theirs: map[string]string{ - "file": "a\nb\nc\nd\ne\nf\n0\n", + theirs: []gittest.TreeEntry{ + {Path: "file", Content: "a\nb\nc\nd\ne\nf\n0\n", Mode: "100644"}, }, expected: map[string]string{ "file": "0\na\nb\nc\nd\ne\nf\n0\n", }, squash: true, expectedResponse: git2go.MergeResult{ - CommitID: "7ef7460f69503265a247e06218391cfa57c521fc", + CommitID: "43853c4a027a67c7e39afa8e7ef0a34a1874ef26", }, }, { desc: "multiple files succeed", - base: map[string]string{ - "1": "foo", - "2": "bar", - "3": "qux", + base: []gittest.TreeEntry{ + {Path: "1", Content: "foo", Mode: "100644"}, + {Path: "2", Content: "bar", Mode: "100644"}, + {Path: "3", Content: "qux", Mode: "100644"}, }, - ours: map[string]string{ - "1": "foo", - "2": "modified", - "3": "qux", + ours: []gittest.TreeEntry{ + {Path: "1", Content: "foo", Mode: "100644"}, + {Path: "2", Content: "modified", Mode: "100644"}, + {Path: "3", Content: "qux", Mode: "100644"}, }, - theirs: map[string]string{ - "1": "modified", - "2": "bar", - "3": "qux", + theirs: []gittest.TreeEntry{ + {Path: "1", Content: "modified", Mode: "100644"}, + {Path: "2", Content: "bar", Mode: "100644"}, + {Path: "3", Content: "qux", Mode: "100644"}, }, expected: map[string]string{ "1": "modified", @@ -238,25 +238,25 @@ func TestMerge_trees(t *testing.T) { "3": "qux", }, expectedResponse: git2go.MergeResult{ - CommitID: "e9be4578f89ea52d44936fb36517e837d698b34b", + CommitID: "6be1fdb2c4116881c7a82575be41618e8a690ff4", }, }, { desc: "multiple files squash succeed", - base: map[string]string{ - "1": "foo", - "2": "bar", - "3": "qux", + base: []gittest.TreeEntry{ + {Path: "1", Content: "foo", Mode: "100644"}, + {Path: "2", Content: "bar", Mode: "100644"}, + {Path: "3", Content: "qux", Mode: "100644"}, }, - ours: map[string]string{ - "1": "foo", - "2": "modified", - "3": "qux", + ours: []gittest.TreeEntry{ + {Path: "1", Content: "foo", Mode: "100644"}, + {Path: "2", Content: "modified", Mode: "100644"}, + {Path: "3", Content: "qux", Mode: "100644"}, }, - theirs: map[string]string{ - "1": "modified", - "2": "bar", - "3": "qux", + theirs: []gittest.TreeEntry{ + {Path: "1", Content: "modified", Mode: "100644"}, + {Path: "2", Content: "bar", Mode: "100644"}, + {Path: "3", Content: "qux", Mode: "100644"}, }, expected: map[string]string{ "1": "modified", @@ -265,19 +265,19 @@ func TestMerge_trees(t *testing.T) { }, squash: true, expectedResponse: git2go.MergeResult{ - CommitID: "a680459fe541be728c8494fb76c233a344c04460", + CommitID: "fe094a98b22ac53e1da1a9eb16118ce49f01fdbe", }, }, { desc: "conflicting merge fails", - base: map[string]string{ - "1": "foo", + base: []gittest.TreeEntry{ + {Path: "1", Content: "foo", Mode: "100644"}, }, - ours: map[string]string{ - "1": "bar", + ours: []gittest.TreeEntry{ + {Path: "1", Content: "bar", Mode: "100644"}, }, - theirs: map[string]string{ - "1": "qux", + theirs: []gittest.TreeEntry{ + {Path: "1", Content: "qux", Mode: "100644"}, }, expectedErr: fmt.Errorf("merge: %w", git2go.ConflictingFilesError{ ConflictingFiles: []string{"1"}, @@ -290,9 +290,9 @@ func TestMerge_trees(t *testing.T) { testcfg.BuildGitalyGit2Go(t, cfg) executor := buildExecutor(t, cfg) - base := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{nil}, tc.base) - ours := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.ours) - theirs := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, tc.theirs) + base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries(tc.base...)) + ours := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.ours...)) + theirs := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(tc.theirs...)) authorDate := time.Date(2020, 7, 30, 7, 45, 50, 0, time.FixedZone("UTC+2", +2*60*60)) committerDate := time.Date(2021, 7, 30, 7, 45, 50, 0, time.FixedZone("UTC+2", +2*60*60)) @@ -327,7 +327,7 @@ func TestMerge_trees(t *testing.T) { require.NoError(t, err) defer repo.Free() - commitOid, err := git.NewOid(response.CommitID) + commitOid, err := libgit2.NewOid(response.CommitID) require.NoError(t, err) commit, err := repo.LookupCommit(commitOid) @@ -358,15 +358,15 @@ func TestMerge_squash(t *testing.T) { testcfg.BuildGitalyGit2Go(t, cfg) executor := buildExecutor(t, cfg) - baseFiles := map[string]string{"file.txt": "b\nc"} - ourFiles := map[string]string{"file.txt": "a\nb\nc"} - theirFiles1 := map[string]string{"file.txt": "b\nc\nd"} - theirFiles2 := map[string]string{"file.txt": "b\nc\nd\ne"} + baseFile := gittest.TreeEntry{Path: "file.txt", Content: "b\nc", Mode: "100644"} + ourFile := gittest.TreeEntry{Path: "file.txt", Content: "a\nb\nc", Mode: "100644"} + theirFile1 := gittest.TreeEntry{Path: "file.txt", Content: "b\nc\nd", Mode: "100644"} + theirFile2 := gittest.TreeEntry{Path: "file.txt", Content: "b\nc\nd\ne", Mode: "100644"} - base := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{nil}, baseFiles) - ours := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, ourFiles) - theirs1 := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, theirFiles1) - theirs2 := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{theirs1}, theirFiles2) + base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries(baseFile)) + ours := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(ourFile)) + theirs1 := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries(theirFile1)) + theirs2 := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(theirs1), gittest.WithTreeEntries(theirFile2)) date := time.Date(2020, 7, 30, 7, 45, 50, 0, time.FixedZone("UTC+2", +2*60*60)) response, err := executor.Merge(ctx, repoProto, git2go.MergeCommand{ @@ -380,15 +380,17 @@ func TestMerge_squash(t *testing.T) { Squash: true, }) require.NoError(t, err) - assert.Equal(t, "027d909803fbb3d17c3b10c1dfe8f120d99392e4", response.CommitID) + assert.Equal(t, "882b43b68d160876e3833dc6bbabf7032058e837", response.CommitID) repo, err := git2goutil.OpenRepository(repoPath) require.NoError(t, err) - commitOid, err := git.NewOid(response.CommitID) + commitOid, err := libgit2.NewOid(response.CommitID) require.NoError(t, err) - isDescendant, err := repo.DescendantOf(commitOid, theirs2) + theirs2Oid, err := libgit2.NewOid(theirs2.String()) + require.NoError(t, err) + isDescendant, err := repo.DescendantOf(commitOid, theirs2Oid) require.NoError(t, err) require.False(t, isDescendant) @@ -396,7 +398,7 @@ func TestMerge_squash(t *testing.T) { require.NoError(t, err) require.Equal(t, uint(1), commit.ParentCount()) - require.Equal(t, ours, commit.ParentId(0)) + require.Equal(t, ours.String(), commit.ParentId(0).String()) tree, err := commit.Tree() require.NoError(t, err) @@ -419,15 +421,21 @@ func TestMerge_recursive(t *testing.T) { repoProto, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0]) - base := cmdtesthelper.BuildCommit(t, repoPath, nil, map[string]string{"base": "base\n"}) + base := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "base", Content: "base\n", Mode: "100644"}, + )) - oursContents := map[string]string{"base": "base\n", "ours": "ours-0\n"} - ours := make([]*git.Oid, git2go.MergeRecursionLimit) - ours[0] = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, oursContents) + ours := make([]git.ObjectID, git2go.MergeRecursionLimit) + ours[0] = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "base", Content: "base\n", Mode: "100644"}, + gittest.TreeEntry{Path: "ours", Content: "ours-0\n", Mode: "100644"}, + )) - theirsContents := map[string]string{"base": "base\n", "theirs": "theirs-0\n"} - theirs := make([]*git.Oid, git2go.MergeRecursionLimit) - theirs[0] = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{base}, theirsContents) + theirs := make([]git.ObjectID, git2go.MergeRecursionLimit) + theirs[0] = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(base), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "base", Content: "base\n", Mode: "100644"}, + gittest.TreeEntry{Path: "theirs", Content: "theirs-0\n", Mode: "100644"}, + )) // We're now creating a set of criss-cross merges which look like the following graph: // @@ -441,13 +449,17 @@ func TestMerge_recursive(t *testing.T) { // is not unique, and as a result the merge will generate virtual merge bases for each of // the criss-cross merges. This operation may thus be heavily expensive to perform. for i := 1; i < git2go.MergeRecursionLimit; i++ { - oursContents["ours"] = fmt.Sprintf("ours-%d\n", i) - oursContents["theirs"] = fmt.Sprintf("theirs-%d\n", i-1) - theirsContents["ours"] = fmt.Sprintf("ours-%d\n", i-1) - theirsContents["theirs"] = fmt.Sprintf("theirs-%d\n", i) - - ours[i] = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{ours[i-1], theirs[i-1]}, oursContents) - theirs[i] = cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{theirs[i-1], ours[i-1]}, theirsContents) + ours[i] = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(ours[i-1], theirs[i-1]), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "base", Content: "base\n", Mode: "100644"}, + gittest.TreeEntry{Path: "ours", Content: fmt.Sprintf("ours-%d\n", i), Mode: "100644"}, + gittest.TreeEntry{Path: "theirs", Content: fmt.Sprintf("theirs-%d\n", i-1), Mode: "100644"}, + )) + + theirs[i] = gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(theirs[i-1], ours[i-1]), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "base", Content: "base\n", Mode: "100644"}, + gittest.TreeEntry{Path: "ours", Content: fmt.Sprintf("ours-%d\n", i-1), Mode: "100644"}, + gittest.TreeEntry{Path: "theirs", Content: fmt.Sprintf("theirs-%d\n", i), Mode: "100644"}, + )) } authorDate := time.Date(2020, 7, 30, 7, 45, 50, 0, time.FixedZone("UTC+2", +2*60*60)) @@ -500,7 +512,7 @@ func TestMerge_recursive(t *testing.T) { repo, err := git2goutil.OpenRepository(repoPath) require.NoError(t, err) - commitOid, err := git.NewOid(response.CommitID) + commitOid, err := libgit2.NewOid(response.CommitID) require.NoError(t, err) commit, err := repo.LookupCommit(commitOid) diff --git a/cmd/gitaly-git2go-v15/rebase_test.go b/cmd/gitaly-git2go-v15/rebase_test.go index a596876f6..a7df2a912 100644 --- a/cmd/gitaly-git2go-v15/rebase_test.go +++ b/cmd/gitaly-git2go-v15/rebase_test.go @@ -11,7 +11,6 @@ import ( git "github.com/libgit2/git2go/v33" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil" - cmdtesthelper "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/testhelper" gitalygit "gitlab.com/gitlab-org/gitaly/v15/internal/git" "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v15/internal/git2go" @@ -125,12 +124,12 @@ func TestRebase_rebase(t *testing.T) { require.NoError(t, err) tree, err := other.Tree() require.NoError(t, err) - newOid, err := repo.CreateCommitFromIds("refs/heads/branch-merged-plus-one", &cmdtesthelper.DefaultAuthor, &cmdtesthelper.DefaultAuthor, "Message", tree.Object.Id(), head.Object.Id()) + newOid, err := repo.CreateCommitFromIds("refs/heads/branch-merged-plus-one", &DefaultAuthor, &DefaultAuthor, "Message", tree.Object.Id(), head.Object.Id()) require.NoError(t, err) - require.Equal(t, "5da601ef10e314884bbade9d5b063be37579ccf9", newOid.String()) + require.Equal(t, "8665d9b4b56f6b8ab8c4128a5549d1820bf68bf5", newOid.String()) }, commitsAhead: 1, - expected: "591b29084164bcc58fa4fb851a3c409290b17bfe", + expected: "56bafb70922008232d171b78930be6cdb722bb39", }, { desc: "With upstream merged into", @@ -146,9 +145,9 @@ func TestRebase_rebase(t *testing.T) { tree, err := index.WriteTreeTo(repo) require.NoError(t, err) - newOid, err := repo.CreateCommitFromIds("refs/heads/csv-plus-merge", &cmdtesthelper.DefaultAuthor, &cmdtesthelper.DefaultAuthor, "Message", tree, ours.Object.Id(), theirs.Object.Id()) + newOid, err := repo.CreateCommitFromIds("refs/heads/csv-plus-merge", &DefaultAuthor, &DefaultAuthor, "Message", tree, ours.Object.Id(), theirs.Object.Id()) require.NoError(t, err) - require.Equal(t, "5cfe4a597b54c8f2b7ae85212f67599a1492009c", newOid.String()) + require.Equal(t, "5b2d6bd7be0b1b9f7e46b64d02fe9882c133a128", newOid.String()) }, commitsAhead: 5, // Same as "Multiple commits" expected: "2f8365edc69d3683e22c4209ae9641642d84dd4a", diff --git a/cmd/gitaly-git2go-v15/revert_test.go b/cmd/gitaly-git2go-v15/revert_test.go index aa85689f5..5cea73d44 100644 --- a/cmd/gitaly-git2go-v15/revert_test.go +++ b/cmd/gitaly-git2go-v15/revert_test.go @@ -12,8 +12,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil" - cmdtesthelper "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/testhelper" + "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v15/internal/git2go" + "gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/config" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg" ) @@ -77,7 +78,7 @@ func TestRevert_validation(t *testing.T) { func TestRevert_trees(t *testing.T) { testcases := []struct { desc string - setupRepo func(t testing.TB, repoPath string) (ours, revert string) + setupRepo func(t testing.TB, cfg config.Cfg, repoPath string) (ours, revert string) expected map[string]string expectedCommitID string expectedErr string @@ -85,20 +86,21 @@ func TestRevert_trees(t *testing.T) { }{ { desc: "trivial revert succeeds", - setupRepo: func(t testing.TB, repoPath string) (ours, revert string) { - baseOid := cmdtesthelper.BuildCommit(t, repoPath, nil, map[string]string{ - "a": "apple", - "b": "banana", - }) - revertOid := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{baseOid}, map[string]string{ - "a": "apple", - "b": "pineapple", - }) - oursOid := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{revertOid}, map[string]string{ - "a": "apple", - "b": "pineapple", - "c": "carrot", - }) + setupRepo: func(t testing.TB, cfg config.Cfg, repoPath string) (ours, revert string) { + baseOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + gittest.TreeEntry{Path: "b", Content: "banana", Mode: "100644"}, + )) + revertOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(baseOid), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + gittest.TreeEntry{Path: "b", Content: "pineapple", Mode: "100644"}, + )) + oursOid := gittest.WriteCommit(t, cfg, repoPath, + gittest.WithParents(revertOid), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + gittest.TreeEntry{Path: "b", Content: "pineapple", Mode: "100644"}, + gittest.TreeEntry{Path: "c", Content: "carrot", Mode: "100644"}, + )) return oursOid.String(), revertOid.String() }, @@ -107,20 +109,20 @@ func TestRevert_trees(t *testing.T) { "b": "banana", "c": "carrot", }, - expectedCommitID: "0be709b57f18ad3f592a8cb7c57f920861392573", + expectedCommitID: "c9a58d2273b265cb229f02a5a88037bbdc96ad26", }, { desc: "conflicting revert fails", - setupRepo: func(t testing.TB, repoPath string) (ours, revert string) { - baseOid := cmdtesthelper.BuildCommit(t, repoPath, nil, map[string]string{ - "a": "apple", - }) - revertOid := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{baseOid}, map[string]string{ - "a": "pineapple", - }) - oursOid := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{revertOid}, map[string]string{ - "a": "carrot", - }) + setupRepo: func(t testing.TB, cfg config.Cfg, repoPath string) (ours, revert string) { + baseOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + )) + revertOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(baseOid), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "pineapple", Mode: "100644"}, + )) + oursOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(revertOid), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "carrot", Mode: "100644"}, + )) return oursOid.String(), revertOid.String() }, @@ -129,16 +131,16 @@ func TestRevert_trees(t *testing.T) { }, { desc: "empty revert fails", - setupRepo: func(t testing.TB, repoPath string) (ours, revert string) { - baseOid := cmdtesthelper.BuildCommit(t, repoPath, nil, map[string]string{ - "a": "apple", - }) - revertOid := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{baseOid}, map[string]string{ - "a": "banana", - }) - oursOid := cmdtesthelper.BuildCommit(t, repoPath, []*git.Oid{revertOid}, map[string]string{ - "a": "apple", - }) + setupRepo: func(t testing.TB, cfg config.Cfg, repoPath string) (ours, revert string) { + baseOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + )) + revertOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(baseOid), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "banana", Mode: "100644"}, + )) + oursOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(revertOid), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + )) return oursOid.String(), revertOid.String() }, @@ -147,10 +149,10 @@ func TestRevert_trees(t *testing.T) { }, { desc: "nonexistent ours fails", - setupRepo: func(t testing.TB, repoPath string) (ours, revert string) { - revertOid := cmdtesthelper.BuildCommit(t, repoPath, nil, map[string]string{ - "a": "apple", - }) + setupRepo: func(t testing.TB, cfg config.Cfg, repoPath string) (ours, revert string) { + revertOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + )) return "nonexistent", revertOid.String() }, @@ -158,10 +160,10 @@ func TestRevert_trees(t *testing.T) { }, { desc: "nonexistent revert fails", - setupRepo: func(t testing.TB, repoPath string) (ours, revert string) { - oursOid := cmdtesthelper.BuildCommit(t, repoPath, nil, map[string]string{ - "a": "apple", - }) + setupRepo: func(t testing.TB, cfg config.Cfg, repoPath string) (ours, revert string) { + oursOid := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithTreeEntries( + gittest.TreeEntry{Path: "a", Content: "apple", Mode: "100644"}, + )) return oursOid.String(), "nonexistent" }, @@ -174,7 +176,7 @@ func TestRevert_trees(t *testing.T) { testcfg.BuildGitalyGit2Go(t, cfg) executor := buildExecutor(t, cfg) - ours, revert := tc.setupRepo(t, repoPath) + ours, revert := tc.setupRepo(t, cfg, repoPath) ctx := testhelper.Context(t) authorDate := time.Date(2020, 7, 30, 7, 45, 50, 0, time.FixedZone("UTC+2", +2*60*60)) diff --git a/cmd/gitaly-git2go-v15/testhelper/testhelper.go b/cmd/gitaly-git2go-v15/testhelper/testhelper.go deleted file mode 100644 index 7ba1e65cd..000000000 --- a/cmd/gitaly-git2go-v15/testhelper/testhelper.go +++ /dev/null @@ -1,48 +0,0 @@ -//go:build static && system_libgit2 -// +build static,system_libgit2 - -package testhelper - -import ( - "testing" - "time" - - git "github.com/libgit2/git2go/v33" - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v15/cmd/gitaly-git2go-v15/git2goutil" -) - -// DefaultAuthor is the author used by BuildCommit -var DefaultAuthor = git.Signature{ - Name: "Foo", - Email: "foo@example.com", - When: time.Date(2020, 1, 1, 1, 1, 1, 0, time.FixedZone("", 2*60*60)), -} - -//nolint: revive,stylecheck // This is unintentionally missing documentation. -func BuildCommit(t testing.TB, repoPath string, parents []*git.Oid, fileContents map[string]string) *git.Oid { - repo, err := git2goutil.OpenRepository(repoPath) - require.NoError(t, err) - defer repo.Free() - - odb, err := repo.Odb() - require.NoError(t, err) - - treeBuilder, err := repo.TreeBuilder() - require.NoError(t, err) - - for file, contents := range fileContents { - oid, err := odb.Write([]byte(contents), git.ObjectBlob) - require.NoError(t, err) - require.NoError(t, treeBuilder.Insert(file, oid, git.FilemodeBlob)) - } - - tree, err := treeBuilder.Write() - require.NoError(t, err) - - var commit *git.Oid - commit, err = repo.CreateCommitFromIds("", &DefaultAuthor, &DefaultAuthor, "Message", tree, parents...) - require.NoError(t, err) - - return commit -} diff --git a/cmd/gitaly-git2go-v15/testhelper_test.go b/cmd/gitaly-git2go-v15/testhelper_test.go index 39c0dad26..21fc90b13 100644 --- a/cmd/gitaly-git2go-v15/testhelper_test.go +++ b/cmd/gitaly-git2go-v15/testhelper_test.go @@ -4,16 +4,41 @@ package main import ( + "fmt" "testing" + "time" + git "github.com/libgit2/git2go/v33" "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v15/internal/git2go" "gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/config" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" ) +// DefaultAuthor is the author used by BuildCommit +var DefaultAuthor = git.Signature{ + Name: "Scrooge McDuck", + Email: "scrooge@mcduck.com", + When: time.Date(2019, 11, 3, 11, 27, 59, 0, time.FixedZone("", 60*60)), +} + func TestMain(m *testing.M) { - testhelper.Run(m) + testhelper.Run(m, testhelper.WithSetup(func() error { + // We use Git2go to access repositories in our tests, so we must tell it to ignore + // any configuration files that happen to exist. We do the same in `main()`, so + // this is not only specific to tests. + for _, configLevel := range []git.ConfigLevel{ + git.ConfigLevelSystem, + git.ConfigLevelXDG, + git.ConfigLevelGlobal, + } { + if err := git.SetSearchPath(configLevel, "/dev/null"); err != nil { + return fmt.Errorf("setting Git2go search path: %s", err) + } + } + + return nil + })) } func buildExecutor(tb testing.TB, cfg config.Cfg) *git2go.Executor { diff --git a/internal/command/command.go b/internal/command/command.go index 4992c6d5b..6dc524e57 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -23,20 +23,6 @@ import ( "gitlab.com/gitlab-org/labkit/tracing" ) -func init() { - // Prevent the environment from affecting git calls by ignoring the configuration files. - // - // This should be done always but we have to wait until 15.0 due to backwards compatibility - // concerns. To fix tests ahead to 15.0, we ignore the global configuration when the package - // has been built under tests. `go test` uses a `.test` suffix on the test binaries. We use - // that to check whether to ignore the globals or not. - // - // See https://gitlab.com/gitlab-org/gitaly/-/issues/3617. - if strings.HasSuffix(os.Args[0], ".test") { - GitEnv = append(GitEnv, "GIT_CONFIG_GLOBAL=/dev/null", "GIT_CONFIG_SYSTEM=/dev/null") - } -} - var ( cpuSecondsTotal = promauto.NewCounterVec( prometheus.CounterOpts{ @@ -89,18 +75,6 @@ var ( ) ) -// GitEnv contains the ENV variables for git commands -var GitEnv = []string{ - // Force english locale for consistency on the output messages - "LANG=en_US.UTF-8", - - // - // PLEASE NOTE: the init of this package adds rules to ignore global git configuration in - // tests. This should really be done always but we can't do this before 15.0 due to backwards - // compatibility concerns. See https://gitlab.com/gitlab-org/gitaly/-/issues/3617. - // -} - // exportedEnvVars contains a list of environment variables // that are always exported to child processes on spawn var exportedEnvVars = []string{ @@ -275,11 +249,11 @@ func New(ctx context.Context, cmd *exec.Cmd, stdin io.Reader, stdout, stderr io. span: span, } - // Explicitly set the environment for the command - env = append(env, "GIT_TERMINAL_PROMPT=0") - - // Export env vars - cmd.Env = append(AllowedEnvironment(os.Environ()), env...) + // Export allowed environment variables as set in the Gitaly process. + cmd.Env = AllowedEnvironment(os.Environ()) + // Append environment variables explicitly requested by thecaller. + cmd.Env = append(cmd.Env, env...) + // And finally inject environment variables required for tracing into the command. cmd.Env = envInjector(ctx, cmd.Env) // Start the command in its own process group (nice for signalling) diff --git a/internal/git/command_factory.go b/internal/git/command_factory.go index a5d127019..17b2a85de 100644 --- a/internal/git/command_factory.go +++ b/internal/git/command_factory.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "path/filepath" + "strings" "sync" "github.com/prometheus/client_golang/prometheus" @@ -147,9 +148,33 @@ func NewExecCommandFactory(cfg config.Cfg, opts ...ExecCommandFactoryOption) (_ // setupGitExecutionEnvironments assembles a Git execution environment that can be used to run Git // commands. It warns if no path was specified in the configuration. func setupGitExecutionEnvironments(cfg config.Cfg, factoryCfg execCommandFactoryConfig) ([]ExecutionEnvironment, func(), error) { + sharedEnvironment := []string{ + // Force English locale for consistency on output messages and to help us debug in + // case we get bug reports from customers whose system-locale would be different. + "LANG=en_US.UTF-8", + // Ask Git to never prompt us for any information like e.g. credentials. + "GIT_TERMINAL_PROMPT=0", + } + + // Prevent the environment from affecting git calls by ignoring the configuration files. + // + // This should be done always but we have to wait until 15.0 due to backwards compatibility + // concerns. To fix tests ahead to 15.0, we ignore the global configuration when the package + // has been built under tests. `go test` uses a `.test` suffix on the test binaries. We use + // that to check whether to ignore the globals or not. + // + // See https://gitlab.com/gitlab-org/gitaly/-/issues/3617. + if strings.HasSuffix(os.Args[0], ".test") { + sharedEnvironment = append(sharedEnvironment, + "GIT_CONFIG_GLOBAL=/dev/null", + "GIT_CONFIG_SYSTEM=/dev/null", + "XDG_CONFIG_HOME=/dev/null", + ) + } + if factoryCfg.gitBinaryPath != "" { return []ExecutionEnvironment{ - {BinaryPath: factoryCfg.gitBinaryPath}, + {BinaryPath: factoryCfg.gitBinaryPath, EnvironmentVariables: sharedEnvironment}, }, func() {}, nil } @@ -168,6 +193,8 @@ func setupGitExecutionEnvironments(cfg config.Cfg, factoryCfg execCommandFactory return nil, nil, fmt.Errorf("constructing Git environment: %w", err) } + execEnv.EnvironmentVariables = append(execEnv.EnvironmentVariables, sharedEnvironment...) + execEnvs = append(execEnvs, execEnv) } @@ -369,7 +396,6 @@ func (cf *ExecCommandFactory) newCommand(ctx context.Context, repo repository.Gi execEnv := cf.GetExecutionEnvironment(ctx) - env = append(env, command.GitEnv...) env = append(env, execEnv.EnvironmentVariables...) execCommand := exec.Command(execEnv.BinaryPath, args...) diff --git a/internal/git/command_factory_test.go b/internal/git/command_factory_test.go index 06d3f0762..3c3aec4fb 100644 --- a/internal/git/command_factory_test.go +++ b/internal/git/command_factory_test.go @@ -170,6 +170,13 @@ func TestCommandFactory_ExecutionEnvironment(t *testing.T) { Git: config.Git{BinPath: "/path/to/myGit"}, }, git.ExecutionEnvironment{ BinaryPath: "/path/to/myGit", + EnvironmentVariables: []string{ + "LANG=en_US.UTF-8", + "GIT_TERMINAL_PROMPT=0", + "GIT_CONFIG_GLOBAL=/dev/null", + "GIT_CONFIG_SYSTEM=/dev/null", + "XDG_CONFIG_HOME=/dev/null", + }, }) }) @@ -178,6 +185,13 @@ func TestCommandFactory_ExecutionEnvironment(t *testing.T) { assertExecEnv(t, config.Cfg{Git: config.Git{}}, git.ExecutionEnvironment{ BinaryPath: "/path/to/env_git", + EnvironmentVariables: []string{ + "LANG=en_US.UTF-8", + "GIT_TERMINAL_PROMPT=0", + "GIT_CONFIG_GLOBAL=/dev/null", + "GIT_CONFIG_SYSTEM=/dev/null", + "XDG_CONFIG_HOME=/dev/null", + }, }) }) @@ -271,6 +285,13 @@ func TestCommandFactory_ExecutionEnvironment(t *testing.T) { assertExecEnv(t, config.Cfg{}, git.ExecutionEnvironment{ BinaryPath: resolvedPath, + EnvironmentVariables: []string{ + "LANG=en_US.UTF-8", + "GIT_TERMINAL_PROMPT=0", + "GIT_CONFIG_GLOBAL=/dev/null", + "GIT_CONFIG_SYSTEM=/dev/null", + "XDG_CONFIG_HOME=/dev/null", + }, }) }) diff --git a/internal/git/gittest/command.go b/internal/git/gittest/command.go index 751f4ee54..b31e57cd3 100644 --- a/internal/git/gittest/command.go +++ b/internal/git/gittest/command.go @@ -62,7 +62,6 @@ func createCommand(t testing.TB, cfg config.Cfg, execCfg ExecConfig, args ...str cmd := exec.CommandContext(ctx, execEnv.BinaryPath, args...) cmd.Env = command.AllowedEnvironment(os.Environ()) - cmd.Env = append(command.GitEnv, cmd.Env...) cmd.Env = append(cmd.Env, "GIT_AUTHOR_DATE=1572776879 +0100", "GIT_COMMITTER_DATE=1572776879 +0100", diff --git a/internal/git2go/executor.go b/internal/git2go/executor.go index d1ab916a1..899c7e64e 100644 --- a/internal/git2go/executor.go +++ b/internal/git2go/executor.go @@ -56,6 +56,7 @@ func (b *Executor) run(ctx context.Context, repo repository.GitRepo, stdin io.Re } env := alternates.Env(repoPath, repo.GetGitObjectDirectory(), repo.GetGitAlternateObjectDirectories()) + env = append(env, b.gitCmdFactory.GetExecutionEnvironment(ctx).EnvironmentVariables...) // Pass the log output directly to gitaly-git2go. No need to reinterpret // these logs as long as the destination is an append-only file. See diff --git a/internal/gitaly/rubyserver/rubyserver.go b/internal/gitaly/rubyserver/rubyserver.go index 1ae315cb3..5ac213e72 100644 --- a/internal/gitaly/rubyserver/rubyserver.go +++ b/internal/gitaly/rubyserver/rubyserver.go @@ -61,7 +61,6 @@ func setupEnv(cfg config.Cfg, gitCmdFactory git.CommandFactory) ([]string, error "GITALY_TOKEN="+cfg.Auth.Token, "GITALY_RUGGED_GIT_CONFIG_SEARCH_PATH="+cfg.Ruby.RuggedGitConfigSearchPath, ) - environment = append(environment, command.GitEnv...) environment = append(environment, gitExecEnv.EnvironmentVariables...) environment = append(environment, env.AllowedRubyEnvironment(os.Environ())...) diff --git a/internal/testhelper/testcfg/build.go b/internal/testhelper/testcfg/build.go index a39a409f4..59ab9ee7a 100644 --- a/internal/testhelper/testcfg/build.go +++ b/internal/testhelper/testcfg/build.go @@ -100,18 +100,7 @@ func BuildBinary(t testing.TB, targetDir, sourcePath string) string { // We need to filter out some environments we set globally in our tests which would // cause Git to not operate correctly. for _, env := range os.Environ() { - shouldExclude := false - for _, prefix := range []string{ - "GIT_DIR=", - "GIT_CONFIG_GLOBAL=", - "GIT_CONFIG_SYSTEM=", - } { - if strings.HasPrefix(env, prefix) { - shouldExclude = true - break - } - } - if !shouldExclude { + if !strings.HasPrefix(env, "GIT_DIR=") { gitEnvironment = append(gitEnvironment, env) } } diff --git a/ruby/bin/gitaly-ruby b/ruby/bin/gitaly-ruby index d37352945..c0f17b1e5 100755 --- a/ruby/bin/gitaly-ruby +++ b/ruby/bin/gitaly-ruby @@ -73,6 +73,8 @@ def set_rugged_search_path return unless search_path Rugged::Settings['search_path_system'] = search_path + Rugged::Settings['search_path_global'] = '/dev/null' + Rugged::Settings['search_path_xdg'] = '/dev/null' end def load_distributed_tracing diff --git a/ruby/spec/spec_helper.rb b/ruby/spec/spec_helper.rb index 52296007e..dcd20550e 100644 --- a/ruby/spec/spec_helper.rb +++ b/ruby/spec/spec_helper.rb @@ -13,6 +13,12 @@ GITLAB_SHELL_DIR = File.join(TMP_DIR, 'gitlab-shell').freeze # overwrite HOME env variable so user global .gitconfig doesn't influence tests ENV["HOME"] = File.join(File.dirname(__FILE__), "/support/helpers/testdata/home") +# Furthermore, overwrite the Rugged search path so that it doesn't pick up any +# gitconfig, either. +Rugged::Settings['search_path_system'] = '/dev/null' +Rugged::Settings['search_path_global'] = '/dev/null' +Rugged::Settings['search_path_xdg'] = '/dev/null' + require 'test_repo_helper' Dir[File.join(__dir__, 'support/helpers/*.rb')].each { |f| require f } |