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:
authorZeger-Jan van de Weg <zegerjan@gitlab.com>2018-10-05 17:58:24 +0300
committerZeger-Jan van de Weg <zegerjan@gitlab.com>2018-10-05 17:58:24 +0300
commit7486edf6d1b0b92c984435be1a189622a50c6375 (patch)
tree4a90d9d31d89c7ba5f9676b29aa34f1240c915d5
parentdf6a8dc7ef30e0a6cc12c6e5d5e26e0458ab8a38 (diff)
parent99f98539d7b231e75c69335d60f6141b764efd99 (diff)
Merge branch 'add-git-protocol-v2' into 'master'
Support Git protocol v2 See merge request gitlab-org/gitaly!844
-rw-r--r--.gitignore1
-rw-r--r--changelogs/unreleased/add-git-protocol-v2.yml5
-rw-r--r--internal/git/helper.go23
-rw-r--r--internal/git/pktline/pktline.go9
-rw-r--r--internal/git/protocol.go24
-rw-r--r--internal/service/smarthttp/inforefs.go8
-rw-r--r--internal/service/smarthttp/inforefs_test.go43
-rw-r--r--internal/service/smarthttp/receive_pack.go3
-rw-r--r--internal/service/smarthttp/receive_pack_test.go35
-rw-r--r--internal/service/smarthttp/upload_pack.go8
-rw-r--r--internal/service/smarthttp/upload_pack_test.go51
-rw-r--r--internal/service/ssh/receive_pack.go1
-rw-r--r--internal/service/ssh/receive_pack_test.go34
-rw-r--r--internal/service/ssh/upload_pack.go8
-rw-r--r--internal/service/ssh/upload_pack_test.go54
-rwxr-xr-xinternal/testhelper/env_git4
-rw-r--r--internal/testhelper/testhelper.go12
17 files changed, 307 insertions, 16 deletions
diff --git a/.gitignore b/.gitignore
index 4b01bfbd4..5799f37c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@
/ruby/.bundle
/ruby/tmp
*.socket
+git-env
diff --git a/changelogs/unreleased/add-git-protocol-v2.yml b/changelogs/unreleased/add-git-protocol-v2.yml
new file mode 100644
index 000000000..b047c3625
--- /dev/null
+++ b/changelogs/unreleased/add-git-protocol-v2.yml
@@ -0,0 +1,5 @@
+---
+title: Support Git protocol v2
+merge_request: 844
+author:
+type: added
diff --git a/internal/git/helper.go b/internal/git/helper.go
index 8af8511d9..e2067a6fe 100644
--- a/internal/git/helper.go
+++ b/internal/git/helper.go
@@ -11,6 +11,15 @@ import (
"gitlab.com/gitlab-org/gitaly/internal/command"
)
+// ProtocolV2 Git sets the protocol 2 string as in the environment
+const ProtocolV2 = "version=2"
+
+// GitV1 Indicates Git protocol 1 is used
+const GitV1 = "v1"
+
+// GitV2 Indicates Git protocol 2 is used
+const GitV2 = "v2"
+
// FallbackTimeValue is the value returned by `SafeTimeParse` in case it
// encounters a parse error. It's the maximum time value possible in golang.
// See https://gitlab.com/gitlab-org/gitaly/issues/556#note_40289573
@@ -72,3 +81,17 @@ func BuildGitOptions(gitOpts []string, otherOpts ...string) []string {
return append(args, otherOpts...)
}
+
+// AddGitProtocolEnv checks whether the request has Git protocol v2
+// and sets this in the environment.
+func AddGitProtocolEnv(req RequestWithGitProtocol, env []string) []string {
+ if req.GetGitProtocol() == ProtocolV2 {
+ env = append(env, fmt.Sprintf("GIT_PROTOCOL=%s", req.GetGitProtocol()))
+
+ gitProtocolRequests.WithLabelValues(GitV2)
+ } else {
+ gitProtocolRequests.WithLabelValues(GitV1)
+ }
+
+ return env
+}
diff --git a/internal/git/pktline/pktline.go b/internal/git/pktline/pktline.go
index c53463a0a..3fe7d9af7 100644
--- a/internal/git/pktline/pktline.go
+++ b/internal/git/pktline/pktline.go
@@ -15,6 +15,7 @@ import (
const (
maxPktSize = 0xffff
+ pktDelim = "0001"
)
var (
@@ -55,12 +56,18 @@ func WriteString(w io.Writer, str string) (int, error) {
return fmt.Fprintf(w, "%04x%s", pktLen, str)
}
-// WriteFlush write a pkt flush packet.
+// WriteFlush writes a pkt flush packet.
func WriteFlush(w io.Writer) error {
_, err := w.Write(flush)
return err
}
+// WriteDelim writes a pkt delim packet.
+func WriteDelim(w io.Writer) error {
+ _, err := fmt.Fprint(w, pktDelim)
+ return err
+}
+
func pktLineSplitter(data []byte, atEOF bool) (advance int, token []byte, err error) {
if len(data) < 4 {
if atEOF && len(data) > 0 {
diff --git a/internal/git/protocol.go b/internal/git/protocol.go
new file mode 100644
index 000000000..0a2458080
--- /dev/null
+++ b/internal/git/protocol.go
@@ -0,0 +1,24 @@
+package git
+
+import (
+ "github.com/prometheus/client_golang/prometheus"
+)
+
+// RequestWithGitProtocol holds requests that respond to GitProtocol
+type RequestWithGitProtocol interface {
+ GetGitProtocol() string
+}
+
+var (
+ gitProtocolRequests = prometheus.NewCounterVec(
+ prometheus.CounterOpts{
+ Name: "gitaly_protocol_requests_total",
+ Help: "Counter of Git protocol requests",
+ },
+ []string{"protocol"},
+ )
+)
+
+func init() {
+ prometheus.MustRegister(gitProtocolRequests)
+}
diff --git a/internal/service/smarthttp/inforefs.go b/internal/service/smarthttp/inforefs.go
index bd7418647..533a32d42 100644
--- a/internal/service/smarthttp/inforefs.go
+++ b/internal/service/smarthttp/inforefs.go
@@ -4,10 +4,12 @@ import (
"context"
"fmt"
"io"
+ "os/exec"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
log "github.com/sirupsen/logrus"
"gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/internal/command"
"gitlab.com/gitlab-org/gitaly/internal/git"
"gitlab.com/gitlab-org/gitaly/internal/git/pktline"
"gitlab.com/gitlab-org/gitaly/internal/helper"
@@ -36,6 +38,8 @@ func handleInfoRefs(ctx context.Context, service string, req *gitalypb.InfoRefsR
"service": service,
}).Debug("handleInfoRefs")
+ env := git.AddGitProtocolEnv(req, []string{})
+
repoPath, err := helper.GetRepoPath(req.Repository)
if err != nil {
return err
@@ -48,7 +52,9 @@ func handleInfoRefs(ctx context.Context, service string, req *gitalypb.InfoRefsR
args = append(args, service, "--stateless-rpc", "--advertise-refs", repoPath)
- cmd, err := git.Command(ctx, req.Repository, args...)
+ osCommand := exec.Command(command.GitPath(), args...)
+ cmd, err := command.New(ctx, osCommand, nil, nil, nil, env...)
+
if err != nil {
if _, ok := status.FromError(err); ok {
return err
diff --git a/internal/service/smarthttp/inforefs_test.go b/internal/service/smarthttp/inforefs_test.go
index 51570d4e7..50777fc29 100644
--- a/internal/service/smarthttp/inforefs_test.go
+++ b/internal/service/smarthttp/inforefs_test.go
@@ -1,11 +1,15 @@
package smarthttp
import (
+ "fmt"
+ "io"
"io/ioutil"
"strings"
"testing"
"gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/internal/config"
+ "gitlab.com/gitlab-org/gitaly/internal/git"
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/streamio"
@@ -50,6 +54,45 @@ func TestSuccessfulInfoRefsUploadPackWithGitConfigOptions(t *testing.T) {
assertGitRefAdvertisement(t, "InfoRefsUploadPack", string(response), "001e# service=git-upload-pack", "0000", []string{})
}
+func TestSuccessfulInfoRefsUploadPackWithGitProtocol(t *testing.T) {
+ defer func(old string) {
+ config.Config.Git.BinPath = old
+ }(config.Config.Git.BinPath)
+ config.Config.Git.BinPath = "../../testhelper/env_git"
+
+ server, serverSocketPath := runSmartHTTPServer(t)
+ defer server.Stop()
+
+ testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
+ defer cleanupFn()
+
+ rpcRequest := &gitalypb.InfoRefsRequest{
+ Repository: testRepo,
+ GitProtocol: git.ProtocolV2,
+ }
+
+ client, _ := newSmartHTTPClient(t, serverSocketPath)
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ c, err := client.InfoRefsUploadPack(ctx, rpcRequest)
+
+ for {
+ _, err := c.Recv()
+ if err != nil {
+ require.Equal(t, io.EOF, err)
+ break
+ }
+ }
+
+ require.NoError(t, err)
+
+ envData, err := testhelper.GetGitEnvData()
+
+ require.NoError(t, err)
+ require.Equal(t, fmt.Sprintf("GIT_PROTOCOL=%s\n", git.ProtocolV2), envData)
+}
+
func makeInfoRefsUploadPackRequest(t *testing.T, serverSocketPath string, rpcRequest *gitalypb.InfoRefsRequest) ([]byte, error) {
client, conn := newSmartHTTPClient(t, serverSocketPath)
defer conn.Close()
diff --git a/internal/service/smarthttp/receive_pack.go b/internal/service/smarthttp/receive_pack.go
index c48800676..9c8683f99 100644
--- a/internal/service/smarthttp/receive_pack.go
+++ b/internal/service/smarthttp/receive_pack.go
@@ -50,6 +50,9 @@ func (s *server) PostReceivePack(stream gitalypb.SmartHTTPService_PostReceivePac
if req.GlUsername != "" {
env = append(env, fmt.Sprintf("GL_USERNAME=%s", req.GlUsername))
}
+
+ env = git.AddGitProtocolEnv(req, env)
+
repoPath, err := helper.GetRepoPath(req.Repository)
if err != nil {
return err
diff --git a/internal/service/smarthttp/receive_pack_test.go b/internal/service/smarthttp/receive_pack_test.go
index 3da59252c..d51bcc234 100644
--- a/internal/service/smarthttp/receive_pack_test.go
+++ b/internal/service/smarthttp/receive_pack_test.go
@@ -11,6 +11,7 @@ import (
"time"
"gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/internal/config"
"gitlab.com/gitlab-org/gitaly/internal/git"
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
@@ -75,6 +76,40 @@ func TestSuccessfulReceivePackRequestWithGitOpts(t *testing.T) {
testhelper.MustRunCommand(t, nil, "git", "-C", repoPath, "show", push.newHead)
}
+func TestSuccessfulReceivePackRequestWithGitProtocol(t *testing.T) {
+ defer func(old string) {
+ config.Config.Git.BinPath = old
+ }(config.Config.Git.BinPath)
+ config.Config.Git.BinPath = "../../testhelper/env_git"
+
+ server, serverSocketPath := runSmartHTTPServer(t)
+ defer server.Stop()
+
+ repo, repoPath, cleanup := testhelper.NewTestRepo(t)
+ defer cleanup()
+
+ client, conn := newSmartHTTPClient(t, serverSocketPath)
+ defer conn.Close()
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ stream, err := client.PostReceivePack(ctx)
+ require.NoError(t, err)
+
+ push := newTestPush(t, nil)
+ firstRequest := &gitalypb.PostReceivePackRequest{Repository: repo, GlId: "user-123", GlRepository: "project-123", GitProtocol: git.ProtocolV2}
+ doPush(t, stream, firstRequest, push.body)
+
+ envData, err := testhelper.GetGitEnvData()
+
+ require.NoError(t, err)
+ require.Equal(t, fmt.Sprintf("GIT_PROTOCOL=%s\n", git.ProtocolV2), envData)
+
+ // The fact that this command succeeds means that we got the commit correctly, no further checks should be needed.
+ testhelper.MustRunCommand(t, nil, "git", "-C", repoPath, "show", push.newHead)
+}
+
func TestFailedReceivePackRequestWithGitOpts(t *testing.T) {
currentGitVersion, _ := git.Version()
if currentGitVersion == "2.9.0" {
diff --git a/internal/service/smarthttp/upload_pack.go b/internal/service/smarthttp/upload_pack.go
index 35b8253b5..03fbc4d3e 100644
--- a/internal/service/smarthttp/upload_pack.go
+++ b/internal/service/smarthttp/upload_pack.go
@@ -4,6 +4,8 @@ import (
"io"
"os/exec"
+ "gitlab.com/gitlab-org/gitaly/internal/git"
+
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
"gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
"gitlab.com/gitlab-org/gitaly/internal/command"
@@ -36,6 +38,7 @@ func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackS
if err != nil {
return err
}
+
if err := validateUploadPackRequest(req); err != nil {
return err
}
@@ -55,6 +58,9 @@ func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackS
stdout := streamio.NewWriter(func(p []byte) error {
return stream.Send(&gitalypb.PostUploadPackResponse{Data: p})
})
+
+ env := git.AddGitProtocolEnv(req, []string{})
+
repoPath, err := helper.GetRepoPath(req.Repository)
if err != nil {
return err
@@ -68,7 +74,7 @@ func (s *server) PostUploadPack(stream gitalypb.SmartHTTPService_PostUploadPackS
args = append(args, "upload-pack", "--stateless-rpc", repoPath)
osCommand := exec.Command(command.GitPath(), args...)
- cmd, err := command.New(stream.Context(), osCommand, stdin, stdout, nil)
+ cmd, err := command.New(stream.Context(), osCommand, stdin, stdout, nil, env...)
if err != nil {
return status.Errorf(codes.Unavailable, "PostUploadPack: cmd: %v", err)
diff --git a/internal/service/smarthttp/upload_pack_test.go b/internal/service/smarthttp/upload_pack_test.go
index 27a4274d6..d2cb3a957 100644
--- a/internal/service/smarthttp/upload_pack_test.go
+++ b/internal/service/smarthttp/upload_pack_test.go
@@ -7,10 +7,14 @@ import (
"io"
"os"
"path"
+ "path/filepath"
"testing"
"time"
"gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
+ "gitlab.com/gitlab-org/gitaly/internal/git"
+
+ "gitlab.com/gitlab-org/gitaly/internal/config"
"gitlab.com/gitlab-org/gitaly/internal/git/pktline"
"gitlab.com/gitlab-org/gitaly/internal/helper"
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
@@ -24,7 +28,7 @@ import (
)
const (
- clientCapabilities = `multi_ack_detailed no-done side-band-64k thin-pack include-tag ofs-delta deepen-since deepen-not agent=git/2.12.2`
+ clientCapabilities = `multi_ack_detailed no-done side-band-64k thin-pack include-tag ofs-delta deepen-since deepen-not agent=git/2.18.0`
)
func TestSuccessfulUploadPackRequest(t *testing.T) {
@@ -147,6 +151,51 @@ func TestUploadPackRequestWithGitConfigOptions(t *testing.T) {
assert.Equal(t, response.String(), "", "Ref is hidden so no response should be received")
}
+func TestUploadPackRequestWithGitProtocol(t *testing.T) {
+ defer func(old string) {
+ config.Config.Git.BinPath = old
+ }(config.Config.Git.BinPath)
+ config.Config.Git.BinPath = "../../testhelper/env_git"
+
+ server, serverSocketPath := runSmartHTTPServer(t)
+ defer server.Stop()
+
+ testRepo := testhelper.TestRepository()
+ testRepoPath, err := helper.GetRepoPath(testRepo)
+ require.NoError(t, err)
+
+ storagePath := testhelper.GitlabTestStoragePath()
+ relativePath, err := filepath.Rel(storagePath, testRepoPath)
+ require.NoError(t, err)
+
+ requestBody := &bytes.Buffer{}
+
+ pktline.WriteString(requestBody, "command=ls-refs\n")
+ pktline.WriteDelim(requestBody)
+ pktline.WriteString(requestBody, "peel\n")
+ pktline.WriteString(requestBody, "symrefs\n")
+ pktline.WriteFlush(requestBody)
+
+ // Only a Git server with v2 will recognize this request.
+ // Git v1 will throw a protocol error.
+ rpcRequest := &gitalypb.PostUploadPackRequest{
+ Repository: &gitalypb.Repository{
+ StorageName: "default",
+ RelativePath: relativePath,
+ },
+ GitProtocol: git.ProtocolV2,
+ }
+
+ // The ref is successfully requested as it is not hidden
+ _, err = makePostUploadPackRequest(t, serverSocketPath, rpcRequest, requestBody)
+ require.NoError(t, err)
+
+ envData, err := testhelper.GetGitEnvData()
+
+ require.NoError(t, err)
+ require.Equal(t, fmt.Sprintf("GIT_PROTOCOL=%s\n", git.ProtocolV2), envData)
+}
+
// This test is here because git-upload-pack returns a non-zero exit code
// on 'deepen' requests even though the request is being handled just
// fine from the client perspective.
diff --git a/internal/service/ssh/receive_pack.go b/internal/service/ssh/receive_pack.go
index e5792f8a1..b291eb9a3 100644
--- a/internal/service/ssh/receive_pack.go
+++ b/internal/service/ssh/receive_pack.go
@@ -51,6 +51,7 @@ func (s *server) SSHReceivePack(stream gitalypb.SSHService_SSHReceivePackServer)
if req.GlRepository != "" {
env = append(env, fmt.Sprintf("GL_REPOSITORY=%s", req.GlRepository))
}
+ env = git.AddGitProtocolEnv(req, env)
repoPath, err := helper.GetRepoPath(req.Repository)
if err != nil {
diff --git a/internal/service/ssh/receive_pack_test.go b/internal/service/ssh/receive_pack_test.go
index 74bf9ebb7..e5e3d3a56 100644
--- a/internal/service/ssh/receive_pack_test.go
+++ b/internal/service/ssh/receive_pack_test.go
@@ -7,10 +7,11 @@ import (
"os"
"os/exec"
"path"
- "strings"
"testing"
"time"
+ "gitlab.com/gitlab-org/gitaly/internal/config"
+
"github.com/golang/protobuf/jsonpb"
"github.com/stretchr/testify/require"
@@ -84,17 +85,36 @@ func TestReceivePackPushSuccess(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if strings.Compare(lHead, rHead) != 0 {
- t.Errorf("local and remote head not equal. push failed: %q != %q", lHead, rHead)
- }
+ require.Equal(t, lHead, rHead, "local and remote head not equal. push failed")
lHead, rHead, err = testCloneAndPush(t, serverSocketPath, pushParams{storageName: testRepo.GetStorageName(), glID: "1", gitConfigOptions: []string{"receive.MaxInputSize=10000"}})
if err != nil {
t.Fatal(err)
}
- if strings.Compare(lHead, rHead) != 0 {
- t.Errorf("local and remote head not equal. push failed: %q != %q", lHead, rHead)
+
+ require.Equal(t, lHead, rHead, "local and remote head not equal. push failed")
+}
+
+func TestReceivePackPushSuccessWithGitProtocol(t *testing.T) {
+ defer func(old string) {
+ config.Config.Git.BinPath = old
+ }(config.Config.Git.BinPath)
+ config.Config.Git.BinPath = "../../testhelper/env_git"
+
+ server, serverSocketPath := runSSHServer(t)
+ defer server.Stop()
+
+ lHead, rHead, err := testCloneAndPush(t, serverSocketPath, pushParams{storageName: testRepo.GetStorageName(), glID: "1", gitProtocol: git.ProtocolV2})
+ if err != nil {
+ t.Fatal(err)
}
+
+ require.Equal(t, lHead, rHead, "local and remote head not equal. push failed")
+
+ envData, err := testhelper.GetGitEnvData()
+
+ require.NoError(t, err)
+ require.Equal(t, fmt.Sprintf("GIT_PROTOCOL=%s\n", git.ProtocolV2), envData)
}
func TestReceivePackPushFailure(t *testing.T) {
@@ -152,6 +172,7 @@ func testCloneAndPush(t *testing.T, serverSocketPath string, params pushParams)
GlRepository: pbTempRepo.GetRelativePath(),
GlId: params.glID,
GitConfigOptions: params.gitConfigOptions,
+ GitProtocol: params.gitProtocol,
})
require.NoError(t, err)
@@ -216,4 +237,5 @@ type pushParams struct {
storageName string
glID string
gitConfigOptions []string
+ gitProtocol string
}
diff --git a/internal/service/ssh/upload_pack.go b/internal/service/ssh/upload_pack.go
index 7867b0a3c..28d3f5296 100644
--- a/internal/service/ssh/upload_pack.go
+++ b/internal/service/ssh/upload_pack.go
@@ -3,6 +3,8 @@ package ssh
import (
"os/exec"
+ "gitlab.com/gitlab-org/gitaly/internal/git"
+
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
"gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
"gitlab.com/gitlab-org/gitaly/internal/command"
@@ -19,6 +21,7 @@ func (s *server) SSHUploadPack(stream gitalypb.SSHService_SSHUploadPackServer) e
if err != nil {
return err
}
+
if err = validateFirstUploadPackRequest(req); err != nil {
return err
}
@@ -33,6 +36,9 @@ func (s *server) SSHUploadPack(stream gitalypb.SSHService_SSHUploadPackServer) e
stderr := streamio.NewWriter(func(p []byte) error {
return stream.Send(&gitalypb.SSHUploadPackResponse{Stderr: p})
})
+
+ env := git.AddGitProtocolEnv(req, []string{})
+
repoPath, err := helper.GetRepoPath(req.Repository)
if err != nil {
return err
@@ -48,7 +54,7 @@ func (s *server) SSHUploadPack(stream gitalypb.SSHService_SSHUploadPackServer) e
osCommand := exec.Command(command.GitPath(), args...)
- cmd, err := command.New(stream.Context(), osCommand, stdin, stdout, stderr)
+ cmd, err := command.New(stream.Context(), osCommand, stdin, stdout, stderr, env...)
if err != nil {
return status.Errorf(codes.Unavailable, "SSHUploadPack: cmd: %v", err)
diff --git a/internal/service/ssh/upload_pack_test.go b/internal/service/ssh/upload_pack_test.go
index 4dbd53d17..34e76a86e 100644
--- a/internal/service/ssh/upload_pack_test.go
+++ b/internal/service/ssh/upload_pack_test.go
@@ -9,6 +9,10 @@ import (
"strings"
"testing"
+ "gitlab.com/gitlab-org/gitaly/internal/git"
+
+ "gitlab.com/gitlab-org/gitaly/internal/config"
+
"github.com/golang/protobuf/jsonpb"
"github.com/stretchr/testify/require"
@@ -90,9 +94,48 @@ func TestUploadPackCloneSuccess(t *testing.T) {
for _, tc := range tests {
t.Run(tc.desc, func(t *testing.T) {
- lHead, rHead, _, _, err := testClone(t, serverSocketPath, testRepo.GetStorageName(), testRepo.GetRelativePath(), localRepoPath, "", tc.cmd)
+ lHead, rHead, _, _, err := testClone(t, serverSocketPath, testRepo.GetStorageName(), testRepo.GetRelativePath(), localRepoPath, "", tc.cmd, "")
+ require.NoError(t, err, "clone failed")
+ require.Equal(t, lHead, rHead, "local and remote head not equal")
+ })
+ }
+}
+
+func TestUploadPackCloneSuccessWithGitProtocol(t *testing.T) {
+ defer func(old string) {
+ config.Config.Git.BinPath = old
+ }(config.Config.Git.BinPath)
+ config.Config.Git.BinPath = "../../testhelper/env_git"
+
+ server, serverSocketPath := runSSHServer(t)
+ defer server.Stop()
+
+ localRepoPath := path.Join(testRepoRoot, "gitlab-test-upload-pack-local")
+
+ tests := []struct {
+ cmd *exec.Cmd
+ desc string
+ }{
+ {
+ cmd: exec.Command("git", "clone", "git@localhost:test/test.git", localRepoPath),
+ desc: "full clone",
+ },
+ {
+ cmd: exec.Command("git", "clone", "--depth", "1", "git@localhost:test/test.git", localRepoPath),
+ desc: "shallow clone",
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.desc, func(t *testing.T) {
+ lHead, rHead, _, _, err := testClone(t, serverSocketPath, testRepo.GetStorageName(), testRepo.GetRelativePath(), localRepoPath, "", tc.cmd, git.ProtocolV2)
require.NoError(t, err, "clone failed")
require.Equal(t, lHead, rHead, "local and remote head not equal")
+
+ envData, err := testhelper.GetGitEnvData()
+
+ require.NoError(t, err)
+ require.Equal(t, fmt.Sprintf("GIT_PROTOCOL=%s\n", git.ProtocolV2), envData)
})
}
}
@@ -105,7 +148,7 @@ func TestUploadPackCloneHideTags(t *testing.T) {
cmd := exec.Command("git", "clone", "--mirror", "git@localhost:test/test.git", localRepoPath)
- _, _, lTags, rTags, err := testClone(t, serverSocketPath, testRepo.GetStorageName(), testRepo.GetRelativePath(), localRepoPath, "transfer.hideRefs=refs/tags", cmd)
+ _, _, lTags, rTags, err := testClone(t, serverSocketPath, testRepo.GetStorageName(), testRepo.GetRelativePath(), localRepoPath, "transfer.hideRefs=refs/tags", cmd, "")
if err != nil {
t.Fatalf("clone failed: %v", err)
@@ -126,18 +169,19 @@ func TestUploadPackCloneFailure(t *testing.T) {
cmd := exec.Command("git", "clone", "git@localhost:test/test.git", localRepoPath)
- _, _, _, _, err := testClone(t, serverSocketPath, "foobar", testRepo.GetRelativePath(), localRepoPath, "", cmd)
+ _, _, _, _, err := testClone(t, serverSocketPath, "foobar", testRepo.GetRelativePath(), localRepoPath, "", cmd, "")
if err == nil {
t.Fatalf("clone didn't fail")
}
}
-func testClone(t *testing.T, serverSocketPath, storageName, relativePath, localRepoPath string, gitConfig string, cmd *exec.Cmd) (string, string, string, string, error) {
+func testClone(t *testing.T, serverSocketPath, storageName, relativePath, localRepoPath string, gitConfig string, cmd *exec.Cmd, gitProtocol string) (string, string, string, string, error) {
defer os.RemoveAll(localRepoPath)
pbTempRepo := &gitalypb.Repository{StorageName: storageName, RelativePath: relativePath}
req := &gitalypb.SSHUploadPackRequest{
- Repository: pbTempRepo,
+ Repository: pbTempRepo,
+ GitProtocol: gitProtocol,
}
if gitConfig != "" {
req.GitConfigOptions = strings.Split(gitConfig, " ")
diff --git a/internal/testhelper/env_git b/internal/testhelper/env_git
new file mode 100755
index 000000000..7739eaeef
--- /dev/null
+++ b/internal/testhelper/env_git
@@ -0,0 +1,4 @@
+#!/bin/sh
+mkdir -p testdata
+env | grep ^GIT_PROTOCOL= > testdata/git-env
+exec git "$@"
diff --git a/internal/testhelper/testhelper.go b/internal/testhelper/testhelper.go
index 5779e54db..3770519e8 100644
--- a/internal/testhelper/testhelper.go
+++ b/internal/testhelper/testhelper.go
@@ -41,6 +41,7 @@ const (
TestRelativePath = "gitlab-test.git"
RepositoryAuthToken = "the-secret-token"
DefaultStorageName = "default"
+ testGitEnv = "testdata/git-env"
)
func init() {
@@ -256,6 +257,17 @@ func ConfigureRuby() {
}
}
+// GetGitEnvData reads and returns the content of testGitEnv
+func GetGitEnvData() (string, error) {
+ gitEnvBytes, err := ioutil.ReadFile(testGitEnv)
+
+ if err != nil {
+ return "", err
+ }
+
+ return string(gitEnvBytes), nil
+}
+
// NewTestGrpcServer creates a GRPC Server for testing purposes
func NewTestGrpcServer(t *testing.T, streamInterceptors []grpc.StreamServerInterceptor, unaryInterceptors []grpc.UnaryServerInterceptor) *grpc.Server {
logger := NewTestLogger(t)