Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Cai <jcai@gitlab.com>2022-07-06 18:33:08 +0300
committerJohn Cai <jcai@gitlab.com>2022-07-06 18:33:08 +0300
commit6944c95243e2b6ed8f783ae903cb9b03ad50e0f9 (patch)
tree3218dcc1d7f632a7823f51cccbe5441ad9c3c1f9
parent1f20b94a3862bf070794390d40b6c91f80648f8f (diff)
parent353927b8f789876c8a6fc69fece765db7b20d1af (diff)
Merge branch 'pks-gittest-drop-worktrees' into 'master'
gittest: Convert most tests that use worktrees See merge request gitlab-org/gitaly!4666
-rw-r--r--internal/git/gittest/commit.go46
-rw-r--r--internal/git/gittest/commit_test.go31
-rw-r--r--internal/git/gittest/ref.go11
-rw-r--r--internal/git/gittest/ref_test.go17
-rw-r--r--internal/git/gittest/repo.go26
-rw-r--r--internal/gitaly/service/diff/raw_test.go141
-rw-r--r--internal/gitaly/service/operations/rebase_test.go289
-rw-r--r--internal/gitaly/service/operations/squash_test.go58
-rw-r--r--internal/gitaly/service/ref/list_refs_test.go64
-rw-r--r--internal/gitaly/service/repository/archive_test.go127
-rw-r--r--internal/gitaly/service/repository/search_files_test.go38
-rw-r--r--internal/gitaly/service/repository/testhelper_test.go10
-rw-r--r--internal/gitaly/service/wiki/find_page_test.go23
-rw-r--r--internal/gitaly/service/wiki/testhelper_test.go8
14 files changed, 513 insertions, 376 deletions
diff --git a/internal/git/gittest/commit.go b/internal/git/gittest/commit.go
index a3cb76864..d0a3f9a01 100644
--- a/internal/git/gittest/commit.go
+++ b/internal/git/gittest/commit.go
@@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"testing"
+ "time"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v15/internal/git"
@@ -22,7 +23,10 @@ const (
type writeCommitConfig struct {
branch string
parents []git.ObjectID
+ authorDate time.Time
+ authorName string
committerName string
+ committerDate time.Time
message string
treeEntries []TreeEntry
treeID git.ObjectID
@@ -77,6 +81,20 @@ func WithTree(treeID git.ObjectID) WriteCommitOption {
}
}
+// WithAuthorName is an option for WriteCommit which will set the author name.
+func WithAuthorName(name string) WriteCommitOption {
+ return func(cfg *writeCommitConfig) {
+ cfg.authorName = name
+ }
+}
+
+// WithAuthorDate is an option for WriteCommit which will set the author date.
+func WithAuthorDate(date time.Time) WriteCommitOption {
+ return func(cfg *writeCommitConfig) {
+ cfg.authorDate = date
+ }
+}
+
// WithCommitterName is an option for WriteCommit which will set the committer name.
func WithCommitterName(name string) WriteCommitOption {
return func(cfg *writeCommitConfig) {
@@ -84,6 +102,13 @@ func WithCommitterName(name string) WriteCommitOption {
}
}
+// WithCommitterDate is an option for WriteCommit which will set the committer date.
+func WithCommitterDate(date time.Time) WriteCommitOption {
+ return func(cfg *writeCommitConfig) {
+ cfg.committerDate = date
+ }
+}
+
// WithAlternateObjectDirectory will cause the commit to be written into the given alternate object
// directory. This can either be an absolute path or a relative path. In the latter case the path
// is considered to be relative to the repository path.
@@ -130,10 +155,22 @@ func WriteCommit(t testing.TB, cfg config.Cfg, repoPath string, opts ...WriteCom
tree = parents[0].String() + "^{tree}"
}
+ if writeCommitConfig.authorName == "" {
+ writeCommitConfig.authorName = committerName
+ }
+
+ if writeCommitConfig.authorDate.IsZero() {
+ writeCommitConfig.authorDate = time.Date(2019, 11, 3, 11, 27, 59, 0, time.FixedZone("UTC+1", 1*60*60))
+ }
+
if writeCommitConfig.committerName == "" {
writeCommitConfig.committerName = committerName
}
+ if writeCommitConfig.committerDate.IsZero() {
+ writeCommitConfig.committerDate = time.Date(2019, 11, 3, 11, 27, 59, 0, time.FixedZone("UTC+1", 1*60*60))
+ }
+
// Use 'commit-tree' instead of 'commit' because we are in a bare
// repository. What we do here is the same as "commit -m message
// --allow-empty".
@@ -156,6 +193,15 @@ func WriteCommit(t testing.TB, cfg config.Cfg, repoPath string, opts ...WriteCom
)
}
+ env = append(env,
+ fmt.Sprintf("GIT_AUTHOR_DATE=%d %s", writeCommitConfig.authorDate.Unix(), writeCommitConfig.authorDate.Format("-0700")),
+ fmt.Sprintf("GIT_AUTHOR_NAME=%s", writeCommitConfig.authorName),
+ fmt.Sprintf("GIT_AUTHOR_EMAIL=%s", committerEmail),
+ fmt.Sprintf("GIT_COMMITTER_DATE=%d %s", writeCommitConfig.committerDate.Unix(), writeCommitConfig.committerDate.Format("-0700")),
+ fmt.Sprintf("GIT_COMMITTER_NAME=%s", writeCommitConfig.committerName),
+ fmt.Sprintf("GIT_COMMITTER_EMAIL=%s", committerEmail),
+ )
+
for _, parent := range parents {
commitArgs = append(commitArgs, "-p", parent.String())
}
diff --git a/internal/git/gittest/commit_test.go b/internal/git/gittest/commit_test.go
index 452fa8eed..c88d2af45 100644
--- a/internal/git/gittest/commit_test.go
+++ b/internal/git/gittest/commit_test.go
@@ -3,6 +3,7 @@ package gittest
import (
"strings"
"testing"
+ "time"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v15/internal/git"
@@ -59,6 +60,36 @@ func TestWriteCommit(t *testing.T) {
}, "\n"),
},
{
+ desc: "with author",
+ opts: []WriteCommitOption{
+ WithAuthorName("John Doe"),
+ WithAuthorDate(time.Date(2005, 4, 7, 15, 13, 13, 0, time.FixedZone("UTC-7", -7*60*60))),
+ },
+ expectedCommit: strings.Join([]string{
+ "tree 91639b9835ff541f312fd2735f639a50bf35d472",
+ "parent " + defaultParentID,
+ "author John Doe <scrooge@mcduck.com> 1112911993 -0700",
+ "committer " + defaultCommitter,
+ "",
+ "message",
+ }, "\n"),
+ },
+ {
+ desc: "with commiter",
+ opts: []WriteCommitOption{
+ WithCommitterName("John Doe"),
+ WithCommitterDate(time.Date(2005, 4, 7, 15, 13, 13, 0, time.FixedZone("UTC-7", -7*60*60))),
+ },
+ expectedCommit: strings.Join([]string{
+ "tree 91639b9835ff541f312fd2735f639a50bf35d472",
+ "parent " + defaultParentID,
+ "author Scrooge McDuck <scrooge@mcduck.com> 1572776879 +0100",
+ "committer John Doe <scrooge@mcduck.com> 1112911993 -0700",
+ "",
+ "message",
+ }, "\n"),
+ },
+ {
desc: "with no parents",
opts: []WriteCommitOption{
WithParents(),
diff --git a/internal/git/gittest/ref.go b/internal/git/gittest/ref.go
index aedbcf3b6..bb1e5a104 100644
--- a/internal/git/gittest/ref.go
+++ b/internal/git/gittest/ref.go
@@ -3,11 +3,22 @@ package gittest
import (
"testing"
+ "github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v15/internal/git"
"gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/config"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/helper/text"
)
// WriteRef writes a reference into the repository pointing to the given object ID.
func WriteRef(t testing.TB, cfg config.Cfg, repoPath string, ref git.ReferenceName, oid git.ObjectID) {
Exec(t, cfg, "-C", repoPath, "update-ref", ref.String(), oid.String())
}
+
+// ResolveRevision resolves the revision to an object ID.
+func ResolveRevision(t testing.TB, cfg config.Cfg, repoPath string, revision string) git.ObjectID {
+ t.Helper()
+ output := Exec(t, cfg, "-C", repoPath, "rev-parse", "--verify", revision)
+ objectID, err := git.NewObjectIDFromHex(text.ChompBytes(output))
+ require.NoError(t, err)
+ return objectID
+}
diff --git a/internal/git/gittest/ref_test.go b/internal/git/gittest/ref_test.go
new file mode 100644
index 000000000..eed9287ee
--- /dev/null
+++ b/internal/git/gittest/ref_test.go
@@ -0,0 +1,17 @@
+package gittest
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/git"
+)
+
+func TestResolveRevision(t *testing.T) {
+ cfg, _, repoPath := setup(t)
+
+ require.Equal(t,
+ git.ObjectID("1e292f8fedd741b75372e19097c76d327140c312"),
+ ResolveRevision(t, cfg, repoPath, "refs/heads/master"),
+ )
+}
diff --git a/internal/git/gittest/repo.go b/internal/git/gittest/repo.go
index 5aa3e5df1..c74412570 100644
--- a/internal/git/gittest/repo.go
+++ b/internal/git/gittest/repo.go
@@ -237,9 +237,6 @@ func RewrittenRepository(ctx context.Context, t testing.TB, cfg config.Cfg, repo
// InitRepoOpts contains options for InitRepo.
type InitRepoOpts struct {
- // WithWorktree determines whether the resulting Git repository should have a worktree or
- // not.
- WithWorktree bool
// WithRelativePath determines the relative path of this repository.
WithRelativePath string
}
@@ -256,22 +253,16 @@ func InitRepo(t testing.TB, cfg config.Cfg, storage config.Storage, opts ...Init
relativePath := opt.WithRelativePath
if relativePath == "" {
- relativePath = NewRepositoryName(t, !opt.WithWorktree)
+ relativePath = NewRepositoryName(t, true)
}
repoPath := filepath.Join(storage.Path, relativePath)
- args := []string{"init"}
- if !opt.WithWorktree {
- args = append(args, "--bare")
- }
+ args := []string{"init", "--bare"}
Exec(t, cfg, append(args, repoPath)...)
repo := InitRepoDir(t, storage.Path, relativePath)
repo.StorageName = storage.Name
- if opt.WithWorktree {
- repo.RelativePath = filepath.Join(repo.RelativePath, ".git")
- }
t.Cleanup(func() { require.NoError(t, os.RemoveAll(repoPath)) })
@@ -283,9 +274,6 @@ type CloneRepoOpts struct {
// RelativePath determines the relative path of newly created Git repository. If unset, the
// relative path is computed via NewRepositoryName.
RelativePath string
- // WithWorktree determines whether the resulting Git repository should have a worktree or
- // not.
- WithWorktree bool
// SourceRepo determines the name of the source repository which shall be cloned. The source
// repository is assumed to be relative to "_build/testrepos". If unset, defaults to
// "gitlab-test.git".
@@ -304,7 +292,7 @@ func CloneRepo(t testing.TB, cfg config.Cfg, storage config.Storage, opts ...Clo
relativePath := opt.RelativePath
if relativePath == "" {
- relativePath = NewRepositoryName(t, !opt.WithWorktree)
+ relativePath = NewRepositoryName(t, true)
}
sourceRepo := opt.SourceRepo
@@ -315,13 +303,7 @@ func CloneRepo(t testing.TB, cfg config.Cfg, storage config.Storage, opts ...Clo
repo := InitRepoDir(t, storage.Path, relativePath)
repo.StorageName = storage.Name
- args := []string{"clone", "--no-hardlinks", "--dissociate"}
- if !opt.WithWorktree {
- args = append(args, "--bare")
- } else {
- // For non-bare repos the relative path is the .git folder inside the path
- repo.RelativePath = filepath.Join(relativePath, ".git")
- }
+ args := []string{"clone", "--no-hardlinks", "--dissociate", "--bare"}
absolutePath := filepath.Join(storage.Path, relativePath)
Exec(t, cfg, append(args, testRepositoryPath(t, sourceRepo), absolutePath)...)
diff --git a/internal/gitaly/service/diff/raw_test.go b/internal/gitaly/service/diff/raw_test.go
index bf6f7b4d9..eda44e902 100644
--- a/internal/gitaly/service/diff/raw_test.go
+++ b/internal/gitaly/service/diff/raw_test.go
@@ -1,56 +1,80 @@
package diff
import (
- "fmt"
"io"
"regexp"
"testing"
+ "time"
"github.com/stretchr/testify/require"
"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"
"gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitaly/v15/streamio"
"google.golang.org/grpc/codes"
)
-func TestSuccessfulRawDiffRequest(t *testing.T) {
+func TestRawDiff_successful(t *testing.T) {
+ t.Parallel()
+
ctx := testhelper.Context(t)
- cfg, repo, repoPath, client := setupDiffService(ctx, t)
+ cfg, repoProto, repoPath, client := setupDiffService(ctx, t)
+ testcfg.BuildGitalyGit2Go(t, cfg)
- rightCommit := "e395f646b1499e8e0279445fc99a0596a65fab7e"
- leftCommit := "8a0f2ee90d940bfb0ba1e14e8214b0649056e4ab"
- rpcRequest := &gitalypb.RawDiffRequest{Repository: repo, RightCommitId: rightCommit, LeftCommitId: leftCommit}
+ gitCmdFactory := gittest.NewCommandFactory(t, cfg)
+ locator := config.NewLocator(cfg)
+ git2goExecutor := git2go.NewExecutor(cfg, gitCmdFactory, locator)
- c, err := client.RawDiff(ctx, rpcRequest)
- require.NoError(t, err)
+ leftCommit := "57290e673a4c87f51294f5216672cbc58d485d25"
+ rightCommit := "e395f646b1499e8e0279445fc99a0596a65fab7e"
- _, sandboxRepoPath := gittest.CloneRepo(t, cfg, cfg.Storages[0], gittest.CloneRepoOpts{
- WithWorktree: true,
+ stream, err := client.RawDiff(ctx, &gitalypb.RawDiffRequest{
+ Repository: repoProto,
+ LeftCommitId: leftCommit,
+ RightCommitId: rightCommit,
})
+ require.NoError(t, err)
- reader := streamio.NewReader(func() ([]byte, error) {
- response, err := c.Recv()
+ rawDiff, err := io.ReadAll(streamio.NewReader(func() ([]byte, error) {
+ response, err := stream.Recv()
return response.GetData(), err
- })
+ }))
+ require.NoError(t, err)
- committerName := "Scrooge McDuck"
- committerEmail := "scrooge@mcduck.com"
- gittest.Exec(t, cfg, "-C", sandboxRepoPath, "reset", "--hard", leftCommit)
+ signature := git2go.Signature{
+ Name: "Scrooge McDuck",
+ Email: "scrooge@mcduck.com",
+ When: time.Unix(12345, 0),
+ }
- gittest.ExecOpts(t, cfg, gittest.ExecConfig{Stdin: reader}, "-C", sandboxRepoPath, "apply")
- gittest.Exec(t, cfg, "-C", sandboxRepoPath, "add", ".")
- gittest.Exec(t, cfg, "-C", sandboxRepoPath,
- "-c", fmt.Sprintf("user.name=%s", committerName),
- "-c", fmt.Sprintf("user.email=%s", committerEmail),
- "commit", "-m", "Applying received raw diff")
+ // Now that we have read the patch in we verify that it indeed round-trips to the same tree
+ // as the right commit is referring to by reapplying the diff on top of the left commit.
+ patchedCommitID, err := git2goExecutor.Apply(ctx, gittest.RewrittenRepository(ctx, t, cfg, repoProto), git2go.ApplyParams{
+ Repository: repoPath,
+ Committer: signature,
+ ParentCommit: leftCommit,
+ Patches: git2go.NewSlicePatchIterator([]git2go.Patch{{
+ Author: signature,
+ Message: "Applying received raw diff",
+ Diff: rawDiff,
+ }}),
+ })
+ require.NoError(t, err)
- expectedTreeStructure := gittest.Exec(t, cfg, "-C", repoPath, "ls-tree", "-r", rightCommit)
- actualTreeStructure := gittest.Exec(t, cfg, "-C", sandboxRepoPath, "ls-tree", "-r", "HEAD")
- require.Equal(t, expectedTreeStructure, actualTreeStructure)
+ // Peel both right commit and patched commit to their trees and assert that they refer to
+ // the same one.
+ require.Equal(t,
+ gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", rightCommit+"^{tree}"),
+ gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", patchedCommitID.String()+"^{tree}"),
+ )
}
-func TestFailedRawDiffRequestDueToValidations(t *testing.T) {
+func TestRawDiff_inputValidation(t *testing.T) {
+ t.Parallel()
+
ctx := testhelper.Context(t)
_, repo, _, client := setupDiffService(ctx, t)
@@ -96,35 +120,64 @@ func TestFailedRawDiffRequestDueToValidations(t *testing.T) {
}
}
-func TestSuccessfulRawPatchRequest(t *testing.T) {
+func TestRawPatch_successful(t *testing.T) {
+ t.Parallel()
+
ctx := testhelper.Context(t)
- cfg, repo, repoPath, client := setupDiffService(ctx, t)
+ cfg, repoProto, repoPath, client := setupDiffService(ctx, t)
+ testcfg.BuildGitalyGit2Go(t, cfg)
+
+ gitCmdFactory := gittest.NewCommandFactory(t, cfg)
+ locator := config.NewLocator(cfg)
+ git2goExecutor := git2go.NewExecutor(cfg, gitCmdFactory, locator)
rightCommit := "e395f646b1499e8e0279445fc99a0596a65fab7e"
leftCommit := "8a0f2ee90d940bfb0ba1e14e8214b0649056e4ab"
- rpcRequest := &gitalypb.RawPatchRequest{Repository: repo, RightCommitId: rightCommit, LeftCommitId: leftCommit}
- c, err := client.RawPatch(ctx, rpcRequest)
+ stream, err := client.RawPatch(ctx, &gitalypb.RawPatchRequest{
+ Repository: repoProto,
+ LeftCommitId: leftCommit,
+ RightCommitId: rightCommit,
+ })
require.NoError(t, err)
- reader := streamio.NewReader(func() ([]byte, error) {
- response, err := c.Recv()
+ rawPatch, err := io.ReadAll(streamio.NewReader(func() ([]byte, error) {
+ response, err := stream.Recv()
return response.GetData(), err
- })
+ }))
+ require.NoError(t, err)
- _, sandboxRepoPath := gittest.CloneRepo(t, cfg, cfg.Storages[0], gittest.CloneRepoOpts{
- WithWorktree: true,
- })
+ signature := git2go.Signature{
+ Name: "Scrooge McDuck",
+ Email: "scrooge@mcduck.com",
+ When: time.Unix(12345, 0),
+ }
- gittest.Exec(t, cfg, "-C", sandboxRepoPath, "reset", "--hard", leftCommit)
- gittest.ExecOpts(t, cfg, gittest.ExecConfig{Stdin: reader}, "-C", sandboxRepoPath, "am")
+ // Now that we have read the patch in we verify that it indeed round-trips to the same tree
+ // as the right commit is referring to by reapplying the diff on top of the left commit.
+ patchedCommitID, err := git2goExecutor.Apply(ctx, gittest.RewrittenRepository(ctx, t, cfg, repoProto), git2go.ApplyParams{
+ Repository: repoPath,
+ Committer: signature,
+ ParentCommit: leftCommit,
+ Patches: git2go.NewSlicePatchIterator([]git2go.Patch{{
+ Author: signature,
+ Message: "Applying received raw patch",
+ Diff: rawPatch,
+ }}),
+ })
+ require.NoError(t, err)
- expectedTreeStructure := gittest.Exec(t, cfg, "-C", repoPath, "ls-tree", "-r", rightCommit)
- actualTreeStructure := gittest.Exec(t, cfg, "-C", sandboxRepoPath, "ls-tree", "-r", "HEAD")
- require.Equal(t, expectedTreeStructure, actualTreeStructure)
+ // Peel both right commit and patched commit to their trees and assert that they refer to
+ // the same one.
+ require.Equal(t,
+ gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", rightCommit+"^{tree}"),
+ gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", patchedCommitID.String()+"^{tree}"),
+ )
}
-func TestFailedRawPatchRequestDueToValidations(t *testing.T) {
+func TestRawPatch_inputValidation(t *testing.T) {
+ t.Parallel()
+
ctx := testhelper.Context(t)
_, repo, _, client := setupDiffService(ctx, t)
@@ -170,7 +223,9 @@ func TestFailedRawPatchRequestDueToValidations(t *testing.T) {
}
}
-func TestRawPatchContainsGitLabSignature(t *testing.T) {
+func TestRawPatch_gitlabSignature(t *testing.T) {
+ t.Parallel()
+
ctx := testhelper.Context(t)
_, repo, _, client := setupDiffService(ctx, t)
diff --git a/internal/gitaly/service/operations/rebase_test.go b/internal/gitaly/service/operations/rebase_test.go
index b1d1f5ce8..25f813af0 100644
--- a/internal/gitaly/service/operations/rebase_test.go
+++ b/internal/gitaly/service/operations/rebase_test.go
@@ -5,8 +5,6 @@ import (
"errors"
"fmt"
"io"
- "path/filepath"
- "strings"
"testing"
"time"
@@ -14,7 +12,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v15/internal/git"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/localrepo"
- "gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/transaction"
"gitlab.com/gitlab-org/gitaly/v15/internal/helper"
"gitlab.com/gitlab-org/gitaly/v15/internal/metadata"
@@ -30,8 +27,9 @@ import (
var rebaseBranchName = "many_files"
-func TestSuccessfulUserRebaseConfirmableRequest(t *testing.T) {
+func TestUserRebaseConfirmable_successful(t *testing.T) {
t.Parallel()
+
ctx := testhelper.Context(t)
ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
@@ -45,7 +43,7 @@ func TestSuccessfulUserRebaseConfirmableRequest(t *testing.T) {
Seed: gittest.SeedGitLabTest,
})
- branchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
+ branchOID := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
rebaseStream, err := client.UserRebaseConfirmable(ctx)
require.NoError(t, err)
@@ -53,7 +51,7 @@ func TestSuccessfulUserRebaseConfirmableRequest(t *testing.T) {
preReceiveHookOutputPath := gittest.WriteEnvToCustomHook(t, repoPath, "pre-receive")
postReceiveHookOutputPath := gittest.WriteEnvToCustomHook(t, repoPath, "post-receive")
- headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", rebaseBranchName, branchSha, repoCopyProto, "master")
+ headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", rebaseBranchName, branchOID, repoCopyProto, "master")
headerRequest.GetHeader().GitPushOptions = pushOptions
require.NoError(t, rebaseStream.Send(headerRequest), "send header")
@@ -75,10 +73,10 @@ func TestSuccessfulUserRebaseConfirmableRequest(t *testing.T) {
_, err = repo.ReadCommit(ctx, git.Revision(firstResponse.GetRebaseSha()))
require.NoError(t, err)
- newBranchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
+ newBranchCommit := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
- require.NotEqual(t, newBranchSha, branchSha)
- require.Equal(t, newBranchSha, firstResponse.GetRebaseSha())
+ require.NotEqual(t, newBranchCommit, branchOID)
+ require.Equal(t, newBranchCommit.String(), firstResponse.GetRebaseSha())
require.True(t, secondResponse.GetRebaseApplied(), "the second rebase is applied")
@@ -191,7 +189,7 @@ func TestUserRebaseConfirmable_skipEmptyCommits(t *testing.T) {
}, rebaseCommit)
}
-func TestUserRebaseConfirmableTransaction(t *testing.T) {
+func TestUserRebaseConfirmable_transaction(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
@@ -249,13 +247,13 @@ func TestUserRebaseConfirmableTransaction(t *testing.T) {
ctx = metadata.IncomingToOutgoing(ctx)
}
- branchSha, err := repo.ResolveRevision(ctx, git.Revision(rebaseBranchName))
+ branchCommitID, err := repo.ResolveRevision(ctx, git.Revision(rebaseBranchName))
require.NoError(t, err)
rebaseStream, err := client.UserRebaseConfirmable(ctx)
require.NoError(t, err)
- headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", rebaseBranchName, branchSha.String(), repoProto, "master")
+ headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", rebaseBranchName, branchCommitID, repoProto, "master")
require.NoError(t, rebaseStream.Send(headerRequest))
_, err = rebaseStream.Recv()
require.NoError(t, err)
@@ -279,7 +277,7 @@ func TestUserRebaseConfirmableTransaction(t *testing.T) {
}
}
-func TestUserRebaseConfirmableStableCommitIDs(t *testing.T) {
+func TestUserRebaseConfirmable_stableCommitIDs(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
@@ -292,7 +290,7 @@ func TestUserRebaseConfirmableStableCommitIDs(t *testing.T) {
require.NoError(t, err)
committerDate := &timestamppb.Timestamp{Seconds: 100000000}
- parentSha := getBranchSha(t, cfg, repoPath, "master")
+ parentSha := gittest.ResolveRevision(t, cfg, repoPath, "master")
require.NoError(t, rebaseStream.Send(&gitalypb.UserRebaseConfirmableRequest{
UserRebaseConfirmableRequestPayload: &gitalypb.UserRebaseConfirmableRequest_Header_{
@@ -301,7 +299,7 @@ func TestUserRebaseConfirmableStableCommitIDs(t *testing.T) {
User: gittest.TestUser,
RebaseId: "1",
Branch: []byte(rebaseBranchName),
- BranchSha: getBranchSha(t, cfg, repoPath, rebaseBranchName),
+ BranchSha: gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName).String(),
RemoteRepository: repoProto,
RemoteBranch: []byte("master"),
Timestamp: committerDate,
@@ -330,7 +328,7 @@ func TestUserRebaseConfirmableStableCommitIDs(t *testing.T) {
Body: []byte("Add a directory with many files to allow testing of default 1,000 entry limit\n\nFor performance reasons, GitLab will add a file viewer limit and only show\nthe first 1,000 entries in a directory. Having this directory with many\nempty files in the test project will make the test easy.\n"),
BodySize: 283,
Id: "c52b98024db0d3af0ccb20ed2a3a93a21cfbba87",
- ParentIds: []string{parentSha},
+ ParentIds: []string{parentSha.String()},
TreeId: "d0305132f880aa0ab4102e56a09cf1343ba34893",
Author: &gitalypb.CommitAuthor{
Name: []byte("Drew Blessing"),
@@ -349,7 +347,7 @@ func TestUserRebaseConfirmableStableCommitIDs(t *testing.T) {
}, commit)
}
-func TestFailedRebaseUserRebaseConfirmableRequestDueToInvalidHeader(t *testing.T) {
+func TestUserRebaseConfirmable_inputValidation(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
@@ -357,7 +355,7 @@ func TestFailedRebaseUserRebaseConfirmableRequestDueToInvalidHeader(t *testing.T
repoCopy, _ := gittest.CloneRepo(t, cfg, cfg.Storages[0])
- branchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
+ branchCommitID := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
testCases := []struct {
desc string
@@ -365,15 +363,15 @@ func TestFailedRebaseUserRebaseConfirmableRequestDueToInvalidHeader(t *testing.T
}{
{
desc: "empty Repository",
- req: buildHeaderRequest(nil, gittest.TestUser, "1", rebaseBranchName, branchSha, repoCopy, "master"),
+ req: buildHeaderRequest(nil, gittest.TestUser, "1", rebaseBranchName, branchCommitID, repoCopy, "master"),
},
{
desc: "empty User",
- req: buildHeaderRequest(repo, nil, "1", rebaseBranchName, branchSha, repoCopy, "master"),
+ req: buildHeaderRequest(repo, nil, "1", rebaseBranchName, branchCommitID, repoCopy, "master"),
},
{
desc: "empty Branch",
- req: buildHeaderRequest(repo, gittest.TestUser, "1", "", branchSha, repoCopy, "master"),
+ req: buildHeaderRequest(repo, gittest.TestUser, "1", "", branchCommitID, repoCopy, "master"),
},
{
desc: "empty BranchSha",
@@ -381,15 +379,15 @@ func TestFailedRebaseUserRebaseConfirmableRequestDueToInvalidHeader(t *testing.T
},
{
desc: "empty RemoteRepository",
- req: buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchSha, nil, "master"),
+ req: buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchCommitID, nil, "master"),
},
{
desc: "empty RemoteBranch",
- req: buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchSha, repoCopy, ""),
+ req: buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchCommitID, repoCopy, ""),
},
{
desc: "invalid branch name",
- req: buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchSha, repoCopy, "+dev:master"),
+ req: buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchCommitID, repoCopy, "+dev:master"),
},
}
@@ -408,7 +406,7 @@ func TestFailedRebaseUserRebaseConfirmableRequestDueToInvalidHeader(t *testing.T
}
}
-func TestAbortedUserRebaseConfirmable(t *testing.T) {
+func TestUserRebaseConfirmable_abortViaClose(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
@@ -431,9 +429,9 @@ func TestAbortedUserRebaseConfirmable(t *testing.T) {
testRepo, testRepoPath := gittest.CreateRepository(ctx, t, cfg, createRepoOpts)
testRepoCopy, _ := gittest.CreateRepository(ctx, t, cfg, createRepoOpts)
- branchSha := getBranchSha(t, cfg, testRepoPath, rebaseBranchName)
+ branchCommitID := gittest.ResolveRevision(t, cfg, testRepoPath, rebaseBranchName)
- headerRequest := buildHeaderRequest(testRepo, gittest.TestUser, fmt.Sprintf("%v", i), rebaseBranchName, branchSha, testRepoCopy, "master")
+ headerRequest := buildHeaderRequest(testRepo, gittest.TestUser, fmt.Sprintf("%v", i), rebaseBranchName, branchCommitID, testRepoCopy, "master")
rebaseStream, err := client.UserRebaseConfirmable(ctx)
require.NoError(t, err)
@@ -461,13 +459,13 @@ func TestAbortedUserRebaseConfirmable(t *testing.T) {
require.Error(t, err)
testhelper.RequireGrpcCode(t, err, tc.code)
- newBranchSha := getBranchSha(t, cfg, testRepoPath, rebaseBranchName)
- require.Equal(t, newBranchSha, branchSha, "branch should not change when the rebase is aborted")
+ newBranchCommitID := gittest.ResolveRevision(t, cfg, testRepoPath, rebaseBranchName)
+ require.Equal(t, newBranchCommitID, branchCommitID, "branch should not change when the rebase is aborted")
})
}
}
-func TestFailedUserRebaseConfirmableDueToApplyBeingFalse(t *testing.T) {
+func TestUserRebaseConfirmable_abortViaApply(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
@@ -479,12 +477,12 @@ func TestFailedUserRebaseConfirmableDueToApplyBeingFalse(t *testing.T) {
Seed: gittest.SeedGitLabTest,
})
- branchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
+ branchCommitID := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
rebaseStream, err := client.UserRebaseConfirmable(ctx)
require.NoError(t, err)
- headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", rebaseBranchName, branchSha, testRepoCopy, "master")
+ headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", rebaseBranchName, branchCommitID, testRepoCopy, "master")
require.NoError(t, rebaseStream.Send(headerRequest), "send header")
firstResponse, err := rebaseStream.Recv()
@@ -504,18 +502,20 @@ func TestFailedUserRebaseConfirmableDueToApplyBeingFalse(t *testing.T) {
_, err = repo.ReadCommit(ctx, git.Revision(firstResponse.GetRebaseSha()))
require.Equal(t, localrepo.ErrObjectNotFound, err, "commit should have been discarded")
- newBranchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
- require.Equal(t, branchSha, newBranchSha, "branch should not change when the rebase is not applied")
- require.NotEqual(t, newBranchSha, firstResponse.GetRebaseSha(), "branch should not be the sha returned when the rebase is not applied")
+ newBranchCommitID := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
+ require.Equal(t, branchCommitID, newBranchCommitID, "branch should not change when the rebase is not applied")
+ require.NotEqual(t, newBranchCommitID, firstResponse.GetRebaseSha(), "branch should not be the sha returned when the rebase is not applied")
}
-func TestFailedUserRebaseConfirmableRequestDueToPreReceiveError(t *testing.T) {
+func TestUserRebaseConfirmable_preReceiveError(t *testing.T) {
t.Parallel()
testhelper.NewFeatureSets(featureflag.UserRebaseConfirmableImprovedErrorHandling).
- Run(t, testFailedUserRebaseConfirmableRequestDueToPreReceiveError)
+ Run(t, testUserRebaseConfirmablePreReceiveError)
}
-func testFailedUserRebaseConfirmableRequestDueToPreReceiveError(t *testing.T, ctx context.Context) {
+func testUserRebaseConfirmablePreReceiveError(t *testing.T, ctx context.Context) {
+ t.Parallel()
+
ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -523,7 +523,7 @@ func testFailedUserRebaseConfirmableRequestDueToPreReceiveError(t *testing.T, ct
Seed: gittest.SeedGitLabTest,
})
- branchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
+ branchCommitID := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
hookContent := []byte("#!/bin/sh\necho 'failure'\nexit 1")
@@ -534,7 +534,7 @@ func testFailedUserRebaseConfirmableRequestDueToPreReceiveError(t *testing.T, ct
rebaseStream, err := client.UserRebaseConfirmable(ctx)
require.NoError(t, err)
- headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, fmt.Sprintf("%v", i), rebaseBranchName, branchSha, repoCopyProto, "master")
+ headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, fmt.Sprintf("%v", i), rebaseBranchName, branchCommitID, repoCopyProto, "master")
require.NoError(t, rebaseStream.Send(headerRequest), "send header")
firstResponse, err := rebaseStream.Recv()
@@ -573,9 +573,9 @@ func testFailedUserRebaseConfirmableRequestDueToPreReceiveError(t *testing.T, ct
require.NoError(t, err)
}
- newBranchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
- require.Equal(t, branchSha, newBranchSha, "branch should not change when the rebase fails due to PreReceiveError")
- require.NotEqual(t, newBranchSha, firstResponse.GetRebaseSha(), "branch should not be the sha returned when the rebase fails due to PreReceiveError")
+ newBranchCommitID := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
+ require.Equal(t, branchCommitID, newBranchCommitID, "branch should not change when the rebase fails due to PreReceiveError")
+ require.NotEqual(t, newBranchCommitID, firstResponse.GetRebaseSha(), "branch should not be the sha returned when the rebase fails due to PreReceiveError")
})
}
}
@@ -587,6 +587,8 @@ func TestUserRebaseConfirmable_gitError(t *testing.T) {
}
func testFailedUserRebaseConfirmableDueToGitError(t *testing.T, ctx context.Context) {
+ t.Parallel()
+
ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
repoCopyProto, _ := gittest.CreateRepository(ctx, t, cfg, gittest.CreateRepositoryConfig{
@@ -594,8 +596,8 @@ func testFailedUserRebaseConfirmableDueToGitError(t *testing.T, ctx context.Cont
})
targetBranch := "rebase-encoding-failure-trigger"
- targetBranchCommitID := getBranchSha(t, cfg, repoPath, targetBranch)
- sourceBranchCommitID := getBranchSha(t, cfg, repoPath, "master")
+ targetBranchCommitID := gittest.ResolveRevision(t, cfg, repoPath, targetBranch)
+ sourceBranchCommitID := gittest.ResolveRevision(t, cfg, repoPath, "master")
rebaseStream, err := client.UserRebaseConfirmable(ctx)
require.NoError(t, err)
@@ -615,8 +617,8 @@ func testFailedUserRebaseConfirmableDueToGitError(t *testing.T, ctx context.Cont
[]byte("README.md"),
},
ConflictingCommitIds: []string{
- sourceBranchCommitID,
- targetBranchCommitID,
+ sourceBranchCommitID.String(),
+ targetBranchCommitID.String(),
},
},
},
@@ -630,138 +632,153 @@ func testFailedUserRebaseConfirmableDueToGitError(t *testing.T, ctx context.Cont
require.Equal(t, io.EOF, err)
}
- newBranchSha := getBranchSha(t, cfg, repoPath, targetBranch)
- require.Equal(t, targetBranchCommitID, newBranchSha, "branch should not change when the rebase fails due to GitError")
+ newBranchCommitID := gittest.ResolveRevision(t, cfg, repoPath, targetBranch)
+ require.Equal(t, targetBranchCommitID, newBranchCommitID, "branch should not change when the rebase fails due to GitError")
}
-func getBranchSha(t *testing.T, cfg config.Cfg, repoPath string, branchName string) string {
- branchSha := string(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", branchName))
- return strings.TrimSpace(branchSha)
-}
-
-func TestRebaseRequestWithDeletedFile(t *testing.T) {
+func TestUserRebaseConfirmable_deletedFileInLocalRepo(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
- gittest.AddWorktree(t, cfg, repoPath, "worktree")
- repoPath = filepath.Join(repoPath, "worktree")
+ ctx, cfg, client := setupOperationsServiceWithoutRepo(t, ctx)
- repo := localrepo.NewTestRepo(t, cfg, repoProto)
+ localRepoProto, localRepoPath := gittest.CreateRepository(ctx, t, cfg)
+ localRepo := localrepo.NewTestRepo(t, cfg, localRepoProto)
- repoCopyProto, _ := gittest.CreateRepository(ctx, t, cfg, gittest.CreateRepositoryConfig{
- Seed: gittest.SeedGitLabTest,
- })
+ remoteRepoProto, remoteRepoPath := gittest.CreateRepository(ctx, t, cfg)
- branch := "rebase-delete-test"
+ // Write the root commit into both repositories as common history.
+ var rootCommitID git.ObjectID
+ for _, path := range []string{localRepoPath, remoteRepoPath} {
+ rootCommitID = gittest.WriteCommit(t, cfg, path,
+ gittest.WithParents(),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: "change-me", Mode: "100644", Content: "unchanged contents"},
+ gittest.TreeEntry{Path: "delete-me", Mode: "100644", Content: "useless stuff"},
+ ),
+ )
+ }
- gittest.Exec(t, cfg, "-C", repoPath, "config", "user.name", string(gittest.TestUser.Name))
- gittest.Exec(t, cfg, "-C", repoPath, "config", "user.email", string(gittest.TestUser.Email))
- gittest.Exec(t, cfg, "-C", repoPath, "checkout", "-b", branch, "master~1")
- gittest.Exec(t, cfg, "-C", repoPath, "rm", "README")
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "-a", "-m", "delete file")
+ // Write a commit into the local repository that deletes a single file.
+ localCommitID := gittest.WriteCommit(t, cfg, localRepoPath,
+ gittest.WithParents(rootCommitID),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: "change-me", Mode: "100644", Content: "unchanged contents"},
+ ),
+ gittest.WithBranch("local"),
+ )
- branchSha := getBranchSha(t, cfg, repoPath, branch)
+ // And then finally write a commit into the remote repository that changes a different file.
+ gittest.WriteCommit(t, cfg, remoteRepoPath,
+ gittest.WithParents(rootCommitID),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: "change-me", Mode: "100644", Content: "modified contents"},
+ gittest.TreeEntry{Path: "delete-me", Mode: "100644", Content: "useless stuff"},
+ ),
+ gittest.WithBranch("remote"),
+ )
- rebaseStream, err := client.UserRebaseConfirmable(ctx)
+ // Send the first request to tell the server to perform the rebase.
+ stream, err := client.UserRebaseConfirmable(ctx)
+ require.NoError(t, err)
+ require.NoError(t, stream.Send(buildHeaderRequest(
+ localRepoProto, gittest.TestUser, "1", "local", localCommitID, remoteRepoProto, "remote",
+ )))
+ firstResponse, err := stream.Recv()
require.NoError(t, err)
- headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", branch, branchSha, repoCopyProto, "master")
- require.NoError(t, rebaseStream.Send(headerRequest), "send header")
-
- firstResponse, err := rebaseStream.Recv()
- require.NoError(t, err, "receive first response")
-
- _, err = repo.ReadCommit(ctx, git.Revision(firstResponse.GetRebaseSha()))
+ _, err = localRepo.ReadCommit(ctx, git.Revision(firstResponse.GetRebaseSha()))
require.Equal(t, localrepo.ErrObjectNotFound, err, "commit should not exist in the normal repo given that it is quarantined")
- applyRequest := buildApplyRequest(true)
- require.NoError(t, rebaseStream.Send(applyRequest), "apply rebase")
-
- secondResponse, err := rebaseStream.Recv()
- require.NoError(t, err, "receive second response")
+ // Send the second request to tell the server to apply the rebase.
+ require.NoError(t, stream.Send(buildApplyRequest(true)))
+ secondResponse, err := stream.Recv()
+ require.NoError(t, err)
+ require.True(t, secondResponse.GetRebaseApplied())
- _, err = rebaseStream.Recv()
+ _, err = stream.Recv()
require.Equal(t, io.EOF, err)
- newBranchSha := getBranchSha(t, cfg, repoPath, branch)
-
- _, err = repo.ReadCommit(ctx, git.Revision(firstResponse.GetRebaseSha()))
- require.NoError(t, err, "look up git commit after rebase is applied")
+ newBranchCommitID := gittest.ResolveRevision(t, cfg, localRepoPath, "local")
- require.NotEqual(t, newBranchSha, branchSha)
- require.Equal(t, newBranchSha, firstResponse.GetRebaseSha())
-
- require.True(t, secondResponse.GetRebaseApplied(), "the second rebase is applied")
+ _, err = localRepo.ReadCommit(ctx, git.Revision(firstResponse.GetRebaseSha()))
+ require.NoError(t, err)
+ require.NotEqual(t, newBranchCommitID, localCommitID)
+ require.Equal(t, newBranchCommitID.String(), firstResponse.GetRebaseSha())
}
-func TestRebaseOntoRemoteBranch(t *testing.T) {
+func TestUserRebaseConfirmable_deletedFileInRemoteRepo(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
-
- repo := localrepo.NewTestRepo(t, cfg, repoProto)
-
- remoteRepo, remoteRepoPath := gittest.CreateRepository(ctx, t, cfg, gittest.CreateRepositoryConfig{
- Seed: gittest.SeedGitLabTest,
- })
- gittest.AddWorktree(t, cfg, remoteRepoPath, "worktree")
- remoteRepoPath = filepath.Join(remoteRepoPath, "worktree")
+ ctx, cfg, client := setupOperationsServiceWithoutRepo(t, ctx)
+
+ localRepoProto, localRepoPath := gittest.CreateRepository(ctx, t, cfg)
+ localRepo := localrepo.NewTestRepo(t, cfg, localRepoProto)
+
+ remoteRepoProto, remoteRepoPath := gittest.CreateRepository(ctx, t, cfg)
+
+ // Write the root commit into both repositories as common history.
+ var rootCommitID git.ObjectID
+ for _, path := range []string{localRepoPath, remoteRepoPath} {
+ rootCommitID = gittest.WriteCommit(t, cfg, path,
+ gittest.WithParents(),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: "unchanged", Mode: "100644", Content: "unchanged contents"},
+ gittest.TreeEntry{Path: "delete-me", Mode: "100644", Content: "useless stuff"},
+ ),
+ gittest.WithBranch("local"),
+ )
+ }
- localBranch := "master"
- localBranchHash := getBranchSha(t, cfg, repoPath, localBranch)
+ // Write a commit into the remote repository that deletes a file.
+ remoteCommitID := gittest.WriteCommit(t, cfg, remoteRepoPath,
+ gittest.WithParents(rootCommitID),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: "unchanged", Mode: "100644", Content: "unchanged contents"},
+ ),
+ gittest.WithBranch("remote"),
+ )
- remoteBranch := "remote-branch"
- gittest.Exec(t, cfg, "-C", remoteRepoPath, "config", "user.name", string(gittest.TestUser.Name))
- gittest.Exec(t, cfg, "-C", remoteRepoPath, "config", "user.email", string(gittest.TestUser.Email))
- gittest.Exec(t, cfg, "-C", remoteRepoPath, "checkout", "-b", remoteBranch, "master")
- gittest.Exec(t, cfg, "-C", remoteRepoPath, "rm", "README")
- gittest.Exec(t, cfg, "-C", remoteRepoPath, "commit", "-a", "-m", "remove README")
- remoteBranchHash := getBranchSha(t, cfg, remoteRepoPath, remoteBranch)
+ _, err := localRepo.ReadCommit(ctx, remoteCommitID.Revision())
+ require.Equal(t, localrepo.ErrObjectNotFound, err, "remote commit should not yet exist in local repository")
+ // Send the first request to tell the server to perform the rebase.
rebaseStream, err := client.UserRebaseConfirmable(ctx)
require.NoError(t, err)
-
- _, err = repo.ReadCommit(ctx, git.Revision(remoteBranchHash))
- require.Equal(t, localrepo.ErrObjectNotFound, err, "remote commit does not yet exist in local repository")
-
- headerRequest := buildHeaderRequest(repoProto, gittest.TestUser, "1", localBranch, localBranchHash, remoteRepo, remoteBranch)
- require.NoError(t, rebaseStream.Send(headerRequest), "send header")
-
+ require.NoError(t, rebaseStream.Send(buildHeaderRequest(
+ localRepoProto, gittest.TestUser, "1", "local", rootCommitID, remoteRepoProto, "remote",
+ )))
firstResponse, err := rebaseStream.Recv()
- require.NoError(t, err, "receive first response")
+ require.NoError(t, err)
- _, err = repo.ReadCommit(ctx, git.Revision(remoteBranchHash))
+ _, err = localRepo.ReadCommit(ctx, remoteCommitID.Revision())
require.Equal(t, localrepo.ErrObjectNotFound, err, "commit should not exist in the normal repo given that it is quarantined")
- applyRequest := buildApplyRequest(true)
- require.NoError(t, rebaseStream.Send(applyRequest), "apply rebase")
-
+ // Send the second request to tell the server to apply the rebase.
+ require.NoError(t, rebaseStream.Send(buildApplyRequest(true)))
secondResponse, err := rebaseStream.Recv()
- require.NoError(t, err, "receive second response")
+ require.NoError(t, err)
+ require.True(t, secondResponse.GetRebaseApplied(), "the second rebase is applied")
_, err = rebaseStream.Recv()
require.Equal(t, io.EOF, err)
- _, err = repo.ReadCommit(ctx, git.Revision(remoteBranchHash))
+ _, err = localRepo.ReadCommit(ctx, remoteCommitID.Revision())
require.NoError(t, err)
- rebasedBranchHash := getBranchSha(t, cfg, repoPath, localBranch)
-
- require.NotEqual(t, rebasedBranchHash, localBranchHash)
- require.Equal(t, rebasedBranchHash, firstResponse.GetRebaseSha())
-
- require.True(t, secondResponse.GetRebaseApplied(), "the second rebase is applied")
+ rebasedBranchCommitID := gittest.ResolveRevision(t, cfg, localRepoPath, "local")
+ require.NotEqual(t, rebasedBranchCommitID, rootCommitID)
+ require.Equal(t, rebasedBranchCommitID.String(), firstResponse.GetRebaseSha())
}
-func TestRebaseFailedWithCode(t *testing.T) {
+func TestUserRebaseConfirmable_failedWithCode(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
- branchSha := getBranchSha(t, cfg, repoPath, rebaseBranchName)
+ branchCommitID := gittest.ResolveRevision(t, cfg, repoPath, rebaseBranchName)
testCases := []struct {
desc string
@@ -774,7 +791,7 @@ func TestRebaseFailedWithCode(t *testing.T) {
repo := proto.Clone(repoProto).(*gitalypb.Repository)
repo.StorageName = "@this-storage-does-not-exist"
- return buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchSha, repo, "master")
+ return buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchCommitID, repo, "master")
},
expectedCode: codes.InvalidArgument,
},
@@ -784,7 +801,7 @@ func TestRebaseFailedWithCode(t *testing.T) {
repo := proto.Clone(repoProto).(*gitalypb.Repository)
repo.RelativePath = ""
- return buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchSha, repo, "master")
+ return buildHeaderRequest(repo, gittest.TestUser, "1", rebaseBranchName, branchCommitID, repo, "master")
},
expectedCode: codes.InvalidArgument,
},
@@ -824,7 +841,7 @@ func rebaseRecvTimeout(bidi gitalypb.OperationService_UserRebaseConfirmableClien
}
}
-func buildHeaderRequest(repo *gitalypb.Repository, user *gitalypb.User, rebaseID string, branchName string, branchSha string, remoteRepo *gitalypb.Repository, remoteBranch string) *gitalypb.UserRebaseConfirmableRequest {
+func buildHeaderRequest(repo *gitalypb.Repository, user *gitalypb.User, rebaseID string, branchName string, commitID git.ObjectID, remoteRepo *gitalypb.Repository, remoteBranch string) *gitalypb.UserRebaseConfirmableRequest {
return &gitalypb.UserRebaseConfirmableRequest{
UserRebaseConfirmableRequestPayload: &gitalypb.UserRebaseConfirmableRequest_Header_{
Header: &gitalypb.UserRebaseConfirmableRequest_Header{
@@ -832,7 +849,7 @@ func buildHeaderRequest(repo *gitalypb.Repository, user *gitalypb.User, rebaseID
User: user,
RebaseId: rebaseID,
Branch: []byte(branchName),
- BranchSha: branchSha,
+ BranchSha: commitID.String(),
RemoteRepository: remoteRepo,
RemoteBranch: []byte(remoteBranch),
},
diff --git a/internal/gitaly/service/operations/squash_test.go b/internal/gitaly/service/operations/squash_test.go
index 72d741ac1..387099e9a 100644
--- a/internal/gitaly/service/operations/squash_test.go
+++ b/internal/gitaly/service/operations/squash_test.go
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"os"
- "path/filepath"
"strings"
"testing"
@@ -323,43 +322,52 @@ func TestUserSquash_renames(t *testing.T) {
t.Parallel()
ctx := testhelper.Context(t)
- ctx, cfg, repoProto, repoPath, client := setupOperationsService(t, ctx)
+ ctx, cfg, client := setupOperationsServiceWithoutRepo(t, ctx)
+
+ repoProto, repoPath := gittest.CreateRepository(ctx, t, cfg)
- gittest.AddWorktree(t, cfg, repoPath, "worktree")
- repoPath = filepath.Join(repoPath, "worktree")
+ gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithBranch("main"))
repo := localrepo.NewTestRepo(t, cfg, repoProto)
originalFilename := "original-file.txt"
renamedFilename := "renamed-file.txt"
- gittest.Exec(t, cfg, "-C", repoPath, "checkout", "-b", "squash-rename-test", "master")
- require.NoError(t, os.WriteFile(filepath.Join(repoPath, originalFilename), []byte("This is a test"), 0o644))
- gittest.Exec(t, cfg, "-C", repoPath, "add", ".")
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "-m", "test file")
-
- startCommitID := text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "HEAD"))
-
- gittest.Exec(t, cfg, "-C", repoPath, "mv", originalFilename, renamedFilename)
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "-a", "-m", "renamed test file")
+ rootCommitID := gittest.WriteCommit(t, cfg, repoPath,
+ gittest.WithParents(),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: originalFilename, Mode: "100644", Content: "This is a test"},
+ ),
+ )
- // Modify the original file in another branch
- gittest.Exec(t, cfg, "-C", repoPath, "checkout", "-b", "squash-rename-branch", startCommitID)
- require.NoError(t, os.WriteFile(filepath.Join(repoPath, originalFilename), []byte("This is a change"), 0o644))
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "-a", "-m", "test")
+ startCommitID := gittest.WriteCommit(t, cfg, repoPath,
+ gittest.WithParents(rootCommitID),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: renamedFilename, Mode: "100644", Content: "This is a test"},
+ ),
+ )
- require.NoError(t, os.WriteFile(filepath.Join(repoPath, originalFilename), []byte("This is another change"), 0o644))
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "-a", "-m", "test")
+ changedCommitID := gittest.WriteCommit(t, cfg, repoPath,
+ gittest.WithParents(rootCommitID),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: originalFilename, Mode: "100644", Content: "This is a change"},
+ ),
+ )
- endCommitID := text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "HEAD"))
+ endCommitID := gittest.WriteCommit(t, cfg, repoPath,
+ gittest.WithParents(changedCommitID),
+ gittest.WithTreeEntries(
+ gittest.TreeEntry{Path: originalFilename, Mode: "100644", Content: "This is another change"},
+ ),
+ )
request := &gitalypb.UserSquashRequest{
Repository: repoProto,
User: gittest.TestUser,
Author: author,
CommitMessage: commitMessage,
- StartSha: startCommitID,
- EndSha: endCommitID,
+ StartSha: startCommitID.String(),
+ EndSha: endCommitID.String(),
}
response, err := client.UserSquash(ctx, request)
@@ -367,7 +375,7 @@ func TestUserSquash_renames(t *testing.T) {
commit, err := repo.ReadCommit(ctx, git.Revision(response.SquashSha))
require.NoError(t, err)
- require.Equal(t, []string{startCommitID}, commit.ParentIds)
+ require.Equal(t, []string{startCommitID.String()}, commit.ParentIds)
require.Equal(t, author.Name, commit.Author.Name)
require.Equal(t, author.Email, commit.Author.Email)
require.Equal(t, gittest.TestUser.Name, commit.Committer.Name)
@@ -375,6 +383,10 @@ func TestUserSquash_renames(t *testing.T) {
require.Equal(t, gittest.TimezoneOffset, string(commit.Committer.Timezone))
require.Equal(t, gittest.TimezoneOffset, string(commit.Author.Timezone))
require.Equal(t, commitMessage, commit.Subject)
+
+ gittest.RequireTree(t, cfg, repoPath, response.SquashSha, []gittest.TreeEntry{
+ {Path: renamedFilename, Mode: "100644", Content: "This is another change", OID: "1b2ae89cca65f0d514f677981f012d708df651fc"},
+ })
}
func TestUserSquash_missingFileOnTargetBranch(t *testing.T) {
diff --git a/internal/gitaly/service/ref/list_refs_test.go b/internal/gitaly/service/ref/list_refs_test.go
index 239c7ecd9..b9df9c5a1 100644
--- a/internal/gitaly/service/ref/list_refs_test.go
+++ b/internal/gitaly/service/ref/list_refs_test.go
@@ -2,11 +2,10 @@ package ref
import (
"io"
- "path/filepath"
"testing"
+ "time"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitaly/v15/internal/git"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest"
"gitlab.com/gitlab-org/gitaly/v15/internal/helper/text"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
@@ -19,28 +18,21 @@ func TestServer_ListRefs(t *testing.T) {
cfg, _, _, client := setupRefService(ctx, t)
repo, repoPath := gittest.CreateRepository(ctx, t, cfg)
- // Checking out a worktree in an empty repository is not possible, so we must first write an empty commit.
- gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch(git.DefaultBranch), gittest.WithParents())
- gittest.AddWorktree(t, cfg, repoPath, "worktree")
- repoPath = filepath.Join(repoPath, "worktree")
- // The worktree is detached, checkout the main so the branch pointer advances
- // as we commit.
- gittest.Exec(t, cfg, "-C", repoPath, "checkout", "main")
- oldCommit := text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "refs/heads/main"))
-
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "--allow-empty", "-m", "commit message")
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "--amend", "--date", "Wed Feb 16 14:01 2011 +0100", "--allow-empty", "--no-edit")
- commit := text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "refs/heads/main"))
+ oldCommitID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents())
+ newCommitID := gittest.WriteCommit(t, cfg, repoPath,
+ gittest.WithParents(oldCommitID),
+ gittest.WithAuthorDate(time.Date(2011, 2, 16, 14, 1, 0, 0, time.FixedZone("UTC+1", +1*60*60))),
+ )
for _, cmd := range [][]string{
- {"update-ref", "refs/heads/main", commit},
- {"tag", "lightweight-tag", commit},
+ {"update-ref", "refs/heads/main", newCommitID.String()},
+ {"tag", "lightweight-tag", newCommitID.String()},
{"tag", "-m", "tag message", "annotated-tag", "refs/heads/main"},
{"symbolic-ref", "refs/heads/symbolic", "refs/heads/main"},
- {"update-ref", "refs/remote/remote-name/remote-branch", commit},
+ {"update-ref", "refs/remote/remote-name/remote-branch", newCommitID.String()},
{"symbolic-ref", "HEAD", "refs/heads/main"},
- {"update-ref", "refs/heads/old", oldCommit},
+ {"update-ref", "refs/heads/old", oldCommitID.String()},
} {
gittest.Exec(t, cfg, append([]string{"-C", repoPath}, cmd...)...)
}
@@ -111,7 +103,7 @@ func TestServer_ListRefs(t *testing.T) {
},
},
expected: []*gitalypb.ListRefsResponse_Reference{
- {Name: []byte("refs/heads/main"), Target: commit},
+ {Name: []byte("refs/heads/main"), Target: newCommitID.String()},
},
},
{
@@ -121,12 +113,12 @@ func TestServer_ListRefs(t *testing.T) {
Patterns: [][]byte{[]byte("refs/")},
},
expected: []*gitalypb.ListRefsResponse_Reference{
- {Name: []byte("refs/heads/main"), Target: commit},
- {Name: []byte("refs/heads/old"), Target: oldCommit},
- {Name: []byte("refs/heads/symbolic"), Target: commit},
- {Name: []byte("refs/remote/remote-name/remote-branch"), Target: commit},
+ {Name: []byte("refs/heads/main"), Target: newCommitID.String()},
+ {Name: []byte("refs/heads/old"), Target: oldCommitID.String()},
+ {Name: []byte("refs/heads/symbolic"), Target: newCommitID.String()},
+ {Name: []byte("refs/remote/remote-name/remote-branch"), Target: newCommitID.String()},
{Name: []byte("refs/tags/annotated-tag"), Target: annotatedTagOID},
- {Name: []byte("refs/tags/lightweight-tag"), Target: commit},
+ {Name: []byte("refs/tags/lightweight-tag"), Target: newCommitID.String()},
},
},
{
@@ -140,9 +132,9 @@ func TestServer_ListRefs(t *testing.T) {
},
},
expected: []*gitalypb.ListRefsResponse_Reference{
- {Name: []byte("refs/heads/old"), Target: oldCommit},
- {Name: []byte("refs/heads/main"), Target: commit},
- {Name: []byte("refs/heads/symbolic"), Target: commit},
+ {Name: []byte("refs/heads/old"), Target: oldCommitID.String()},
+ {Name: []byte("refs/heads/main"), Target: newCommitID.String()},
+ {Name: []byte("refs/heads/symbolic"), Target: newCommitID.String()},
},
},
{
@@ -152,11 +144,11 @@ func TestServer_ListRefs(t *testing.T) {
Patterns: [][]byte{[]byte("refs/heads/*"), []byte("refs/tags/*")},
},
expected: []*gitalypb.ListRefsResponse_Reference{
- {Name: []byte("refs/heads/main"), Target: commit},
- {Name: []byte("refs/heads/old"), Target: oldCommit},
- {Name: []byte("refs/heads/symbolic"), Target: commit},
+ {Name: []byte("refs/heads/main"), Target: newCommitID.String()},
+ {Name: []byte("refs/heads/old"), Target: oldCommitID.String()},
+ {Name: []byte("refs/heads/symbolic"), Target: newCommitID.String()},
{Name: []byte("refs/tags/annotated-tag"), Target: annotatedTagOID},
- {Name: []byte("refs/tags/lightweight-tag"), Target: commit},
+ {Name: []byte("refs/tags/lightweight-tag"), Target: newCommitID.String()},
},
},
{
@@ -167,12 +159,12 @@ func TestServer_ListRefs(t *testing.T) {
Patterns: [][]byte{[]byte("refs/heads/*"), []byte("refs/tags/*")},
},
expected: []*gitalypb.ListRefsResponse_Reference{
- {Name: []byte("HEAD"), Target: commit},
- {Name: []byte("refs/heads/main"), Target: commit},
- {Name: []byte("refs/heads/old"), Target: oldCommit},
- {Name: []byte("refs/heads/symbolic"), Target: commit},
+ {Name: []byte("HEAD"), Target: newCommitID.String()},
+ {Name: []byte("refs/heads/main"), Target: newCommitID.String()},
+ {Name: []byte("refs/heads/old"), Target: oldCommitID.String()},
+ {Name: []byte("refs/heads/symbolic"), Target: newCommitID.String()},
{Name: []byte("refs/tags/annotated-tag"), Target: annotatedTagOID},
- {Name: []byte("refs/tags/lightweight-tag"), Target: commit},
+ {Name: []byte("refs/tags/lightweight-tag"), Target: newCommitID.String()},
},
},
} {
diff --git a/internal/gitaly/service/repository/archive_test.go b/internal/gitaly/service/repository/archive_test.go
index cdb347617..d66944817 100644
--- a/internal/gitaly/service/repository/archive_test.go
+++ b/internal/gitaly/service/repository/archive_test.go
@@ -31,8 +31,9 @@ const (
lfsBody = "hello world\n"
)
-func TestGetArchiveSuccess(t *testing.T) {
+func TestGetArchive_success(t *testing.T) {
t.Parallel()
+
ctx := testhelper.Context(t)
_, repo, _, client := setupRepositoryService(ctx, t)
@@ -148,13 +149,7 @@ func TestGetArchiveSuccess(t *testing.T) {
data, err := consumeArchive(stream)
require.NoError(t, err)
- archiveFile, err := os.Create(filepath.Join(testhelper.TempDir(t), "archive"))
- require.NoError(t, err)
-
- _, err = archiveFile.Write(data)
- require.NoError(t, err)
-
- contents := string(compressedFileContents(t, format, archiveFile.Name()))
+ contents := compressedFileContents(t, format, data)
for _, content := range tc.contents {
require.Contains(t, contents, tc.prefix+content)
@@ -282,8 +277,9 @@ func TestGetArchive_includeLfsBlobs(t *testing.T) {
}
}
-func TestGetArchiveFailure(t *testing.T) {
+func TestGetArchive_inputValidation(t *testing.T) {
t.Parallel()
+
ctx := testhelper.Context(t)
_, repo, _, client := setupRepositoryService(ctx, t)
@@ -408,68 +404,57 @@ func TestGetArchiveFailure(t *testing.T) {
}
}
-func TestGetArchivePathInjection(t *testing.T) {
+func TestGetArchive_pathInjection(t *testing.T) {
t.Parallel()
- ctx := testhelper.Context(t)
- cfg, repo, repoPath, client := setupRepositoryServiceWithWorktree(ctx, t)
-
- // Adding a temp directory representing the .ssh directory
- sshDirectory := testhelper.TempDir(t)
-
- // Adding an empty authorized_keys file
- authorizedKeysPath := filepath.Join(sshDirectory, "authorized_keys")
-
- authorizedKeysFile, err := os.Create(authorizedKeysPath)
- require.NoError(t, err)
- require.NoError(t, authorizedKeysFile.Close())
-
- // Create the directory on the repository
- repoExploitPath := filepath.Join(repoPath, "--output=", authorizedKeysPath)
- require.NoError(t, os.MkdirAll(repoExploitPath, os.ModeDir|0o755))
-
- f, err := os.Create(filepath.Join(repoExploitPath, "id_12345.pub"))
- require.NoError(t, err)
-
- evilPubKeyFile := `#
- ssh-ed25519 my_super_evil_ssh_pubkey
- #`
- _, err = fmt.Fprint(f, evilPubKeyFile)
- require.NoError(t, err)
- require.NoError(t, f.Close())
-
- // Add the directory to the repository
- gittest.Exec(t, cfg, "-C", repoPath, "add", ".")
- gittest.Exec(t, cfg, "-C", repoPath, "commit", "-m", "adding fake key file")
- commitID := strings.TrimRight(string(gittest.Exec(t, cfg, "-C", repoPath, "rev-parse", "HEAD")), "\n")
-
- injectionPath := fmt.Sprintf("--output=%s", authorizedKeysPath)
-
- req := &gitalypb.GetArchiveRequest{
+ ctx := testhelper.Context(t)
+ cfg, repo, repoPath, client := setupRepositoryService(ctx, t)
+
+ // It used to be possible to inject options into `git-archive(1)`, with the worst outcome
+ // being that an adversary may create or overwrite arbitrary files in the filesystem in case
+ // they passed `--output`.
+ //
+ // We pretend that the adversary wants to override a fixed file `/non/existent`. In
+ // practice, thus would be something more interesting like `/etc/shadow` or `allowed_keys`.
+ // We then create a file inside the repository itself that has `--output=/non/existent` as
+ // relative path. This is done to verify that git-archive(1) indeed treats the parameter as
+ // a path and does not interpret it as an option.
+ outputPath := "/non/existent"
+
+ commitID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithTree(gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{
+ {Path: "--output=", Mode: "040000", OID: gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{
+ {Path: "non", Mode: "040000", OID: gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{
+ {Path: "existent", Mode: "040000", OID: gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{
+ {Path: "injected file", Mode: "100644", Content: "injected content"},
+ })},
+ })},
+ })},
+ })))
+
+ // And now we fire the request path our bogus path to try and overwrite the output path.
+ stream, err := client.GetArchive(ctx, &gitalypb.GetArchiveRequest{
Repository: repo,
- CommitId: commitID,
+ CommitId: commitID.String(),
Prefix: "",
Format: gitalypb.GetArchiveRequest_TAR,
- Path: []byte(injectionPath),
- }
-
- stream, err := client.GetArchive(ctx, req)
- require.NoError(t, err)
-
- _, err = consumeArchive(stream)
+ Path: []byte("--output=" + outputPath),
+ })
require.NoError(t, err)
- authorizedKeysFile, err = os.Open(authorizedKeysPath)
+ content, err := consumeArchive(stream)
require.NoError(t, err)
- defer authorizedKeysFile.Close()
- authorizedKeysFileBytes, err := io.ReadAll(authorizedKeysFile)
- require.NoError(t, err)
- authorizedKeysFileStat, err := authorizedKeysFile.Stat()
- require.NoError(t, err)
-
- require.NotContains(t, string(authorizedKeysFileBytes), evilPubKeyFile) // this should fail first in pre-fix failing test
- require.Zero(t, authorizedKeysFileStat.Size())
+ require.NoFileExists(t, outputPath)
+ require.Equal(t,
+ strings.Join([]string{
+ "/",
+ "/--output=/",
+ "/--output=/non/",
+ "/--output=/non/existent/",
+ "/--output=/non/existent/injected file",
+ }, "\n"),
+ compressedFileContents(t, gitalypb.GetArchiveRequest_TAR, content),
+ )
}
func TestGetArchive_environment(t *testing.T) {
@@ -547,19 +532,23 @@ func TestGetArchive_environment(t *testing.T) {
}
}
-func compressedFileContents(t *testing.T, format gitalypb.GetArchiveRequest_Format, name string) []byte {
+func compressedFileContents(t *testing.T, format gitalypb.GetArchiveRequest_Format, contents []byte) string {
+ path := filepath.Join(testhelper.TempDir(t), "archive")
+ require.NoError(t, os.WriteFile(path, contents, 0o644))
+
switch format {
case gitalypb.GetArchiveRequest_TAR:
- return testhelper.MustRunCommand(t, nil, "tar", "tf", name)
+ return text.ChompBytes(testhelper.MustRunCommand(t, nil, "tar", "tf", path))
case gitalypb.GetArchiveRequest_TAR_GZ:
- return testhelper.MustRunCommand(t, nil, "tar", "ztf", name)
+ return text.ChompBytes(testhelper.MustRunCommand(t, nil, "tar", "ztf", path))
case gitalypb.GetArchiveRequest_TAR_BZ2:
- return testhelper.MustRunCommand(t, nil, "tar", "jtf", name)
+ return text.ChompBytes(testhelper.MustRunCommand(t, nil, "tar", "jtf", path))
case gitalypb.GetArchiveRequest_ZIP:
- return testhelper.MustRunCommand(t, nil, "unzip", "-l", name)
+ return text.ChompBytes(testhelper.MustRunCommand(t, nil, "unzip", "-l", path))
+ default:
+ require.FailNow(t, "unsupported archive format: %v", format)
+ return ""
}
-
- return nil
}
func consumeArchive(stream gitalypb.RepositoryService_GetArchiveClient) ([]byte, error) {
diff --git a/internal/gitaly/service/repository/search_files_test.go b/internal/gitaly/service/repository/search_files_test.go
index 835bcbc4e..b314f50ae 100644
--- a/internal/gitaly/service/repository/search_files_test.go
+++ b/internal/gitaly/service/repository/search_files_test.go
@@ -2,10 +2,7 @@ package repository
import (
"bytes"
- "fmt"
"io"
- "os"
- "path/filepath"
"strings"
"testing"
@@ -152,55 +149,52 @@ func TestSearchFilesByContentSuccessful(t *testing.T) {
func TestSearchFilesByContentLargeFile(t *testing.T) {
t.Parallel()
- ctx := testhelper.Context(t)
- cfg, repo, repoPath, client := setupRepositoryServiceWithWorktree(ctx, t)
+ ctx := testhelper.Context(t)
- committerName := "Scrooge McDuck"
- committerEmail := "scrooge@mcduck.com"
+ cfg, repo, repoPath, client := setupRepositoryService(ctx, t)
- largeFiles := []struct {
+ for _, tc := range []struct {
+ desc string
filename string
line string
repeated int
query string
}{
{
+ desc: "large file",
filename: "large_file_of_abcdefg_2mb",
line: "abcdefghi\n", // 10 bytes
repeated: 210000,
query: "abcdefg",
},
{
+ desc: "large file with unicode",
filename: "large_file_of_unicode_1.5mb",
line: "你见天吃了什么东西?\n", // 22 bytes
repeated: 70000,
query: "什么东西",
},
- }
-
- for _, largeFile := range largeFiles {
- t.Run(largeFile.filename, func(t *testing.T) {
- require.NoError(t, os.WriteFile(filepath.Join(repoPath, largeFile.filename), bytes.Repeat([]byte(largeFile.line), largeFile.repeated), 0o644))
- // By default, the worktree is detached. Checkout master so the branch advances with the commit.
- gittest.Exec(t, cfg, "-C", repoPath, "checkout", "master")
- gittest.Exec(t, cfg, "-C", repoPath, "add", ".")
- gittest.Exec(t, cfg, "-C", repoPath,
- "-c", fmt.Sprintf("user.name=%s", committerName),
- "-c", fmt.Sprintf("user.email=%s", committerEmail), "commit", "-m", "large file commit", "--", largeFile.filename)
+ } {
+ t.Run(tc.filename, func(t *testing.T) {
+ gittest.WriteCommit(t, cfg, repoPath, gittest.WithTreeEntries(gittest.TreeEntry{
+ Path: tc.filename,
+ Mode: "100644",
+ Content: strings.Repeat(tc.line, tc.repeated),
+ }), gittest.WithBranch("master"))
stream, err := client.SearchFilesByContent(ctx, &gitalypb.SearchFilesByContentRequest{
Repository: repo,
- Query: largeFile.query,
+ Query: tc.query,
Ref: []byte("master"),
ChunkedResponse: true,
})
require.NoError(t, err)
- resp, err := consumeFilenameByContentChunked(stream)
+ response, err := consumeFilenameByContentChunked(stream)
require.NoError(t, err)
- require.Equal(t, largeFile.repeated, len(bytes.Split(bytes.TrimRight(resp[0], "\n"), []byte("\n"))))
+ require.Equal(t, tc.repeated, len(bytes.Split(bytes.TrimRight(response[0], "\n"), []byte("\n"))))
})
}
}
diff --git a/internal/gitaly/service/repository/testhelper_test.go b/internal/gitaly/service/repository/testhelper_test.go
index 5024918ca..79fb534d3 100644
--- a/internal/gitaly/service/repository/testhelper_test.go
+++ b/internal/gitaly/service/repository/testhelper_test.go
@@ -3,7 +3,6 @@ package repository
import (
"context"
"os"
- "path/filepath"
"reflect"
"runtime"
"testing"
@@ -196,15 +195,6 @@ func setupRepositoryServiceWithoutRepo(t testing.TB, opts ...testserver.GitalySe
return cfg, client
}
-func setupRepositoryServiceWithWorktree(ctx context.Context, t testing.TB, opts ...testserver.GitalyServerOpt) (config.Cfg, *gitalypb.Repository, string, gitalypb.RepositoryServiceClient) {
- cfg, repo, repoPath, client := setupRepositoryService(ctx, t, opts...)
-
- gittest.AddWorktree(t, cfg, repoPath, "worktree")
- repoPath = filepath.Join(repoPath, "worktree")
-
- return cfg, repo, repoPath, client
-}
-
func gitalyOrPraefect(gitalyMsg, praefectMsg string) string {
if testhelper.IsPraefectEnabled() {
return praefectMsg
diff --git a/internal/gitaly/service/wiki/find_page_test.go b/internal/gitaly/service/wiki/find_page_test.go
index 885c4f5df..06f67a186 100644
--- a/internal/gitaly/service/wiki/find_page_test.go
+++ b/internal/gitaly/service/wiki/find_page_test.go
@@ -1,9 +1,7 @@
package wiki
import (
- "fmt"
"io"
- "path/filepath"
"testing"
"github.com/stretchr/testify/require"
@@ -473,17 +471,13 @@ func testSuccessfulWikiFindPageRequestWithTrailers(t *testing.T, cfg config.Cfg,
gittest.WithMessage("main branch, empty commit"),
)
+ // Include UTF-8 to ensure encoding is handled.
page1Name := "Home Pagé"
- createTestWikiPage(t, cfg, client, wikiRepo, repoPath, createWikiPageOpts{title: page1Name})
-
- gittest.AddWorktree(t, cfg, repoPath, "worktree")
- worktreePath := filepath.Join(repoPath, "worktree")
- gittest.Exec(t, cfg, "-C", worktreePath, "checkout", "main")
- gittest.Exec(t, cfg, "-C", worktreePath,
- // Include UTF-8 to ensure encoding is handled
- "-c", fmt.Sprintf("user.name=%s", "Scróoge McDuck"),
- "-c", fmt.Sprintf("user.email=%s", "scrooge@mcduck.com"),
- "commit", "--amend", "-m", "Empty commit", "-s")
+ author := "Scróoge McDuck"
+ createTestWikiPage(t, cfg, client, wikiRepo, repoPath, createWikiPageOpts{
+ title: page1Name,
+ authorName: author,
+ })
request := &gitalypb.WikiFindPageRequest{
Repository: wikiRepo,
@@ -496,6 +490,7 @@ func testSuccessfulWikiFindPageRequestWithTrailers(t *testing.T, cfg config.Cfg,
receivedPage := readFullWikiPageFromWikiFindPageClient(t, c)
require.Equal(t, page1Name, string(receivedPage.Name))
- receivedContent := receivedPage.GetRawData()
- require.NotNil(t, receivedContent)
+ require.NotNil(t, receivedPage.GetRawData())
+ require.Equal(t, author, string(receivedPage.GetVersion().GetCommit().GetAuthor().GetName()))
+ require.Equal(t, author, string(receivedPage.GetVersion().GetCommit().GetCommitter().GetName()))
}
diff --git a/internal/gitaly/service/wiki/testhelper_test.go b/internal/gitaly/service/wiki/testhelper_test.go
index 8fbed8ef4..5402870c9 100644
--- a/internal/gitaly/service/wiki/testhelper_test.go
+++ b/internal/gitaly/service/wiki/testhelper_test.go
@@ -29,6 +29,7 @@ type createWikiPageOpts struct {
content []byte
format string
forceContentEmpty bool
+ authorName string
}
var mockPageContent = bytes.Repeat([]byte("Mock wiki page content"), 10000)
@@ -121,8 +122,13 @@ func writeWikiPage(t *testing.T, client gitalypb.WikiServiceClient, wikiRepo *gi
format = opts.format
}
+ authorName := opts.authorName
+ if authorName == "" {
+ authorName = "Ahmad Sherif"
+ }
+
commitDetails := &gitalypb.WikiCommitDetails{
- Name: []byte("Ahmad Sherif"),
+ Name: []byte(authorName),
Email: []byte("ahmad@gitlab.com"),
Message: []byte("Add " + opts.title),
UserId: int32(1),