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:
authorPaul Okstad <pokstad@gitlab.com>2020-10-14 08:58:44 +0300
committerPaul Okstad <pokstad@gitlab.com>2020-10-14 08:58:44 +0300
commitc0ba6b3b67598563a14ea7be5f538787354d39be (patch)
tree6758a9480e104dc4079886891ff20cac146ae0fa
parentadd508ab63a157dc9a89bcbc7a56eb42465aa732 (diff)
parent31953a811f40d0ef9a9b1722ecd4611336e4c66f (diff)
Merge branch 'smh-user-commit-files-tests' into 'master'
Extend UserCommitFiles test suite See merge request gitlab-org/gitaly!2636
-rw-r--r--internal/gitaly/service/operations/commit_files_test.go936
1 files changed, 878 insertions, 58 deletions
diff --git a/internal/gitaly/service/operations/commit_files_test.go b/internal/gitaly/service/operations/commit_files_test.go
index 391ba9c24..5ef05f171 100644
--- a/internal/gitaly/service/operations/commit_files_test.go
+++ b/internal/gitaly/service/operations/commit_files_test.go
@@ -1,7 +1,9 @@
package operations
import (
+ "bytes"
"context"
+ "encoding/base64"
"fmt"
"strconv"
"testing"
@@ -13,13 +15,784 @@ import (
"gitlab.com/gitlab-org/gitaly/proto/go/gitalypb"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
)
var (
commitFilesMessage = []byte("Change files")
)
-func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags context.Context) {
+func testImplementations(t *testing.T, test func(t *testing.T, ctx context.Context)) {
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ for _, tc := range []struct {
+ desc string
+ context context.Context
+ }{
+ {desc: "ruby", context: ctx},
+ } {
+ t.Run(tc.desc, func(t *testing.T) { test(t, tc.context) })
+ }
+}
+
+func TestUserCommitFiles(t *testing.T) {
+ testImplementations(t, testUserCommitFiles)
+}
+
+func testUserCommitFiles(t *testing.T, ctx context.Context) {
+ type treeEntry struct {
+ Mode string
+ Path string
+ Content string
+ }
+
+ requireTreeEntries := func(t testing.TB, repoPath, branch string, expectedEntries []treeEntry) {
+ t.Helper()
+
+ var actualEntries []treeEntry
+
+ output := bytes.TrimSpace(testhelper.MustRunCommand(t, nil, "git", "-C", repoPath, "ls-tree", "-r", branch))
+
+ if len(output) > 0 {
+ for _, line := range bytes.Split(output, []byte("\n")) {
+ // Format: <mode> SP <type> SP <object> TAB <file>
+ tabSplit := bytes.Split(line, []byte("\t"))
+ spaceSplit := bytes.Split(tabSplit[0], []byte(" "))
+ path := string(tabSplit[1])
+ actualEntries = append(actualEntries, treeEntry{
+ Mode: string(spaceSplit[0]),
+ Path: path,
+ Content: string(testhelper.MustRunCommand(t, nil, "git", "-C", repoPath, "show", branch+":"+path)),
+ })
+ }
+ }
+
+ require.Equal(t, expectedEntries, actualEntries)
+ }
+
+ const (
+ DefaultMode = "100644"
+ ExecutableMode = "100755"
+ )
+
+ type step struct {
+ actions []*gitalypb.UserCommitFilesRequest
+ error error
+ indexError string
+ repoCreated bool
+ branchCreated bool
+ treeEntries []treeEntry
+ }
+
+ for _, tc := range []struct {
+ desc string
+ steps []step
+ }{
+ {
+ desc: "create directory",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "directory-1/.gitkeep"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create directory ignores mode and content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_CREATE_DIR,
+ FilePath: []byte("directory-1"),
+ ExecuteFilemode: true,
+ Base64Content: true,
+ },
+ },
+ }),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "directory-1/.gitkeep"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create directory created duplicate",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ createDirHeaderRequest("directory-1"),
+ },
+ indexError: "A directory with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create directory with traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("../directory-1"),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "create directory existing duplicate",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "directory-1/.gitkeep"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory-1"),
+ },
+ indexError: "A directory with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create directory with files name",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("file-1"),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create file with directory traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("../file-1"),
+ actionContentRequest("content-1"),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "create file without content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ actionContentRequest(" content-2"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1 content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create file with base64 content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createBase64FileHeaderRequest("file-1"),
+ actionContentRequest(base64.StdEncoding.EncodeToString([]byte("content-1"))),
+ actionContentRequest(base64.StdEncoding.EncodeToString([]byte(" content-2"))),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1 content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "create duplicate file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ createFileHeaderRequest("file-1"),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "create file overwrites directory",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("file-1"),
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update created file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ updateFileHeaderRequest("file-1"),
+ actionContentRequest("content-2"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update base64 content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ updateBase64FileHeaderRequest("file-1"),
+ actionContentRequest(base64.StdEncoding.EncodeToString([]byte("content-2"))),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update ignores mode",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_UPDATE,
+ FilePath: []byte("file-1"),
+ ExecuteFilemode: true,
+ },
+ },
+ }),
+ actionContentRequest("content-2"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ updateFileHeaderRequest("file-1"),
+ actionContentRequest("content-2"),
+ },
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-2"},
+ },
+ },
+ },
+ },
+ {
+ desc: "update non-existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ updateFileHeaderRequest("non-existing"),
+ actionContentRequest("content"),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move file with traversal in source",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("../original-file", "moved-file", true),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "move file with traversal in destination",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("original-file", "../moved-file", true),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "move created file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("content-1"),
+ moveFileHeaderRequest("original-file", "moved-file", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move ignores mode",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("content-1"),
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_MOVE,
+ FilePath: []byte("moved-file"),
+ PreviousPath: []byte("original-file"),
+ ExecuteFilemode: true,
+ InferContent: true,
+ },
+ },
+ }),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "moving directory fails",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createDirHeaderRequest("directory"),
+ moveFileHeaderRequest("directory", "moved-directory", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move file inferring content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("original-content"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "original-file", Content: "original-content"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("original-file", "moved-file", true),
+ actionContentRequest("ignored-content"),
+ },
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "original-content"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move file with non-existing source",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("non-existing", "destination-file", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move file with already existing destination file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("source-file"),
+ createFileHeaderRequest("already-existing"),
+ moveFileHeaderRequest("source-file", "already-existing", true),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ // seems like a bug in the original implementation to allow overwriting a
+ // directory
+ desc: "move file with already existing destination directory",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("source-file"),
+ actionContentRequest("source-content"),
+ createDirHeaderRequest("already-existing"),
+ moveFileHeaderRequest("source-file", "already-existing", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "already-existing", Content: "source-content"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move file providing content",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("original-file"),
+ actionContentRequest("original-content"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "original-file", Content: "original-content"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("original-file", "moved-file", false),
+ actionContentRequest("new-content"),
+ },
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "moved-file", Content: "new-content"},
+ },
+ },
+ },
+ },
+ {
+ desc: "mark non-existing file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("file-1", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "mark executable file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ chmodFileHeaderRequest("file-1", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("file-1", true),
+ },
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "mark file executable with directory traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("../file-1", true),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "mark created file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ chmodFileHeaderRequest("file-1", true),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "mark existing file executable",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ repoCreated: true,
+ branchCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ chmodFileHeaderRequest("file-1", true),
+ },
+ treeEntries: []treeEntry{
+ {Mode: ExecutableMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ },
+ },
+ {
+ desc: "move non-existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ moveFileHeaderRequest("non-existing", "should-not-be-created", true),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "move doesn't overwrite a file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ createFileHeaderRequest("file-2"),
+ actionContentRequest("content-2"),
+ moveFileHeaderRequest("file-1", "file-2", true),
+ },
+ indexError: "A file with this name already exists",
+ },
+ },
+ },
+ {
+ desc: "delete non-existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ deleteFileHeaderRequest("non-existing"),
+ },
+ indexError: "A file with this name doesn't exist",
+ },
+ },
+ },
+ {
+ desc: "delete file with directory traversal",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ deleteFileHeaderRequest("../file-1"),
+ },
+ indexError: "Path cannot include directory traversal",
+ },
+ },
+ },
+ {
+ desc: "delete created file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ deleteFileHeaderRequest("file-1"),
+ },
+ branchCreated: true,
+ repoCreated: true,
+ },
+ },
+ },
+ {
+ desc: "delete existing file",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ createFileHeaderRequest("file-1"),
+ actionContentRequest("content-1"),
+ },
+ branchCreated: true,
+ repoCreated: true,
+ treeEntries: []treeEntry{
+ {Mode: DefaultMode, Path: "file-1", Content: "content-1"},
+ },
+ },
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ deleteFileHeaderRequest("file-1"),
+ },
+ },
+ },
+ },
+ {
+ desc: "invalid action",
+ steps: []step{
+ {
+ actions: []*gitalypb.UserCommitFilesRequest{
+ actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: -1,
+ },
+ },
+ }),
+ },
+ error: status.Error(codes.Unknown, "NoMethodError: undefined method `downcase' for -1:Integer"),
+ },
+ },
+ },
+ } {
+ t.Run(tc.desc, func(t *testing.T) {
+ repo, repoPath, clean := testhelper.InitBareRepo(t)
+ defer clean()
+
+ serverSocketPath, stop := runOperationServiceServer(t)
+ defer stop()
+
+ client, conn := newOperationClient(t, serverSocketPath)
+ defer conn.Close()
+
+ const branch = "master"
+
+ for i, step := range tc.steps {
+ stream, err := client.UserCommitFiles(ctx)
+ require.NoError(t, err)
+
+ headerRequest := headerRequest(repo, testhelper.TestUser, branch, []byte("commit message"))
+ setAuthorAndEmail(headerRequest, []byte("Author Name"), []byte("author.email@example.com"))
+ require.NoError(t, stream.Send(headerRequest))
+
+ for j, action := range step.actions {
+ require.NoError(t, stream.Send(action), "step %d, action %d", i+1, j+1)
+ }
+
+ resp, err := stream.CloseAndRecv()
+ require.Equal(t, step.error, err)
+ if step.error != nil {
+ continue
+ }
+
+ require.Equal(t, step.indexError, resp.IndexError, "step %d", i+1)
+ if step.indexError != "" {
+ continue
+ }
+
+ require.Equal(t, step.branchCreated, resp.BranchUpdate.BranchCreated, "step %d", i+1)
+ require.Equal(t, step.repoCreated, resp.BranchUpdate.RepoCreated, "step %d", i+1)
+ requireTreeEntries(t, repoPath, branch, step.treeEntries)
+ }
+ })
+ }
+}
+
+func TestSuccessfulUserCommitFilesRequest(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequest)
+}
+
+func testSuccessfulUserCommitFilesRequest(t *testing.T, ctx context.Context) {
testRepo, testRepoPath, cleanup := testhelper.NewTestRepo(t)
defer cleanup()
@@ -32,7 +805,6 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
newRepo, newRepoPath, newRepoCleanupFn := testhelper.InitBareRepo(t)
defer newRepoCleanupFn()
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
filePath := "héllo/wörld"
authorName := []byte("Jane Doe")
authorEmail := []byte("janedoe@gitlab.com")
@@ -82,7 +854,6 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
- ctx := metadata.NewOutgoingContext(ctxWithFeatureFlags, md)
headerRequest := headerRequest(tc.repo, testhelper.TestUser, tc.branchName, commitFilesMessage)
setAuthorAndEmail(headerRequest, authorName, authorEmail)
@@ -104,7 +875,7 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
require.Equal(t, tc.repoCreated, resp.GetBranchUpdate().GetRepoCreated())
require.Equal(t, tc.branchCreated, resp.GetBranchUpdate().GetBranchCreated())
- headCommit, err := log.GetCommit(ctxWithFeatureFlags, tc.repo, tc.branchName)
+ headCommit, err := log.GetCommit(ctx, tc.repo, tc.branchName)
require.NoError(t, err)
require.Equal(t, authorName, headCommit.Author.Name)
require.Equal(t, testhelper.TestUser.Name, headCommit.Committer.Name)
@@ -125,23 +896,17 @@ func testSuccessfulUserCommitFilesRequest(t *testing.T, ctxWithFeatureFlags cont
}
}
-func TestSuccessfulUserCommitFilesRequest(t *testing.T) {
- ctx, cancel := testhelper.Context()
- defer cancel()
-
- testSuccessfulUserCommitFilesRequest(t, ctx)
+func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestMove)
}
-func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
+func testSuccessfulUserCommitFilesRequestMove(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
client, conn := newOperationClient(t, serverSocketPath)
defer conn.Close()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
branchName := "master"
previousFilePath := "README"
filePath := "NEWREADME"
@@ -162,8 +927,6 @@ func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
defer cleanupFn()
origFileContent := testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "show", branchName+":"+previousFilePath)
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
headerRequest := headerRequest(testRepo, testhelper.TestUser, branchName, commitFilesMessage)
setAuthorAndEmail(headerRequest, authorName, authorEmail)
actionsRequest1 := moveFileHeaderRequest(previousFilePath, filePath, tc.infer)
@@ -196,6 +959,10 @@ func TestSuccessfulUserCommitFilesRequestMove(t *testing.T) {
}
func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestForceCommit)
+}
+
+func testSuccessfulUserCommitFilesRequestForceCommit(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -205,20 +972,15 @@ func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
testRepo, testRepoPath, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
authorName := []byte("Jane Doe")
authorEmail := []byte("janedoe@gitlab.com")
targetBranchName := "feature"
startBranchName := []byte("master")
- startBranchCommit, err := log.GetCommit(ctxOuter, testRepo, string(startBranchName))
+ startBranchCommit, err := log.GetCommit(ctx, testRepo, string(startBranchName))
require.NoError(t, err)
- targetBranchCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ targetBranchCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
mergeBaseOut := testhelper.MustRunCommand(t, nil, "git", "-C", testRepoPath, "merge-base", targetBranchCommit.Id, startBranchCommit.Id)
@@ -240,7 +1002,7 @@ func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
require.NoError(t, err)
update := resp.GetBranchUpdate()
- newTargetBranchCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ newTargetBranchCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, newTargetBranchCommit.Id, update.CommitId)
@@ -248,6 +1010,10 @@ func TestSuccessfulUserCommitFilesRequestForceCommit(t *testing.T) {
}
func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestStartSha)
+}
+
+func testSuccessfulUserCommitFilesRequestStartSha(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -257,14 +1023,9 @@ func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
targetBranchName := "new"
- startCommit, err := log.GetCommit(ctxOuter, testRepo, "master")
+ startCommit, err := log.GetCommit(ctx, testRepo, "master")
require.NoError(t, err)
headerRequest := headerRequest(testRepo, testhelper.TestUser, targetBranchName, commitFilesMessage)
@@ -280,7 +1041,7 @@ func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
require.NoError(t, err)
update := resp.GetBranchUpdate()
- newTargetBranchCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ newTargetBranchCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, newTargetBranchCommit.Id, update.CommitId)
@@ -288,6 +1049,10 @@ func TestSuccessfulUserCommitFilesRequestStartSha(t *testing.T) {
}
func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestStartShaRemoteRepository)
+}
+
+func testSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -297,17 +1062,18 @@ func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T)
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
newRepo, _, newRepoCleanupFn := testhelper.InitBareRepo(t)
defer newRepoCleanupFn()
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
+ for key, values := range testhelper.GitalyServersMetadata(t, serverSocketPath) {
+ for _, value := range values {
+ ctx = metadata.AppendToOutgoingContext(ctx, key, value)
+ }
+ }
+
targetBranchName := "new"
- startCommit, err := log.GetCommit(ctxOuter, testRepo, "master")
+ startCommit, err := log.GetCommit(ctx, testRepo, "master")
require.NoError(t, err)
headerRequest := headerRequest(newRepo, testhelper.TestUser, targetBranchName, commitFilesMessage)
@@ -324,7 +1090,7 @@ func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T)
require.NoError(t, err)
update := resp.GetBranchUpdate()
- newTargetBranchCommit, err := log.GetCommit(ctxOuter, newRepo, targetBranchName)
+ newTargetBranchCommit, err := log.GetCommit(ctx, newRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, newTargetBranchCommit.Id, update.CommitId)
@@ -332,6 +1098,10 @@ func TestSuccessfulUserCommitFilesRequestStartShaRemoteRepository(t *testing.T)
}
func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *testing.T) {
+ testImplementations(t, testSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature)
+}
+
+func testSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -341,10 +1111,6 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
testRepo, _, cleanupFn := testhelper.InitBareRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
targetBranchName := "master"
testCases := []struct {
@@ -366,7 +1132,6 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
headerRequest := headerRequest(testRepo, tc.user, targetBranchName, commitFilesMessage)
setAuthorAndEmail(headerRequest, tc.user.Name, tc.user.Email)
@@ -377,7 +1142,7 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
_, err = stream.CloseAndRecv()
require.NoError(t, err)
- newCommit, err := log.GetCommit(ctxOuter, testRepo, targetBranchName)
+ newCommit, err := log.GetCommit(ctx, testRepo, targetBranchName)
require.NoError(t, err)
require.Equal(t, tc.author.Name, newCommit.Author.Name, "author name")
@@ -389,6 +1154,10 @@ func TestSuccessfulUserCommitFilesRequestWithSpecialCharactersInSignature(t *tes
}
func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
+ testImplementations(t, testFailedUserCommitFilesRequestDueToHooks)
+}
+
+func testFailedUserCommitFilesRequestDueToHooks(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -398,9 +1167,6 @@ func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
testRepo, testRepoPath, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
branchName := "feature"
filePath := "my/file.txt"
headerRequest := headerRequest(testRepo, testhelper.TestUser, branchName, commitFilesMessage)
@@ -413,8 +1179,7 @@ func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
remove, err := testhelper.WriteCustomHook(testRepoPath, hookName, hookContent)
require.NoError(t, err)
defer remove()
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
+
stream, err := client.UserCommitFiles(ctx)
require.NoError(t, err)
require.NoError(t, stream.Send(headerRequest))
@@ -431,6 +1196,10 @@ func TestFailedUserCommitFilesRequestDueToHooks(t *testing.T) {
}
func TestFailedUserCommitFilesRequestDueToIndexError(t *testing.T) {
+ testImplementations(t, testFailedUserCommitFilesRequestDueToIndexError)
+}
+
+func testFailedUserCommitFilesRequestDueToIndexError(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -440,11 +1209,6 @@ func TestFailedUserCommitFilesRequestDueToIndexError(t *testing.T) {
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
testCases := []struct {
desc string
requests []*gitalypb.UserCommitFilesRequest
@@ -503,6 +1267,10 @@ func TestFailedUserCommitFilesRequestDueToIndexError(t *testing.T) {
}
func TestFailedUserCommitFilesRequest(t *testing.T) {
+ testImplementations(t, testFailedUserCommitFilesRequest)
+}
+
+func testFailedUserCommitFilesRequest(t *testing.T, ctx context.Context) {
serverSocketPath, stop := runOperationServiceServer(t)
defer stop()
@@ -512,11 +1280,6 @@ func TestFailedUserCommitFilesRequest(t *testing.T) {
testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
defer cleanupFn()
- ctxOuter, cancel := testhelper.Context()
- defer cancel()
-
- md := testhelper.GitalyServersMetadata(t, serverSocketPath)
- ctx := metadata.NewOutgoingContext(ctxOuter, md)
branchName := "feature"
testCases := []struct {
@@ -626,6 +1389,17 @@ func getHeader(headerRequest *gitalypb.UserCommitFilesRequest) *gitalypb.UserCom
return headerRequest.UserCommitFilesRequestPayload.(*gitalypb.UserCommitFilesRequest_Header).Header
}
+func createDirHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_CREATE_DIR,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
func createFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
return actionRequest(&gitalypb.UserCommitFilesAction{
UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
@@ -638,6 +1412,41 @@ func createFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
})
}
+func createBase64FileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_CREATE,
+ Base64Content: true,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
+func updateFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_UPDATE,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
+func updateBase64FileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_UPDATE,
+ FilePath: []byte(filePath),
+ Base64Content: true,
+ },
+ },
+ })
+}
+
func chmodFileHeaderRequest(filePath string, executeFilemode bool) *gitalypb.UserCommitFilesRequest {
return actionRequest(&gitalypb.UserCommitFilesAction{
UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
@@ -663,6 +1472,17 @@ func moveFileHeaderRequest(previousPath, filePath string, infer bool) *gitalypb.
})
}
+func deleteFileHeaderRequest(filePath string) *gitalypb.UserCommitFilesRequest {
+ return actionRequest(&gitalypb.UserCommitFilesAction{
+ UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Header{
+ Header: &gitalypb.UserCommitFilesActionHeader{
+ Action: gitalypb.UserCommitFilesActionHeader_DELETE,
+ FilePath: []byte(filePath),
+ },
+ },
+ })
+}
+
func actionContentRequest(content string) *gitalypb.UserCommitFilesRequest {
return actionRequest(&gitalypb.UserCommitFilesAction{
UserCommitFilesActionPayload: &gitalypb.UserCommitFilesAction_Content{