Commit ba8d951b authored by Nick Thomas's avatar Nick Thomas

Respect the ShowAllRefs flag for upload-pack operations

parent bbad7443
...@@ -15,6 +15,7 @@ import ( ...@@ -15,6 +15,7 @@ import (
"time" "time"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/api" "gitlab.com/gitlab-org/gitlab-workhorse/internal/api"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/git"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly" "gitlab.com/gitlab-org/gitlab-workhorse/internal/gitaly"
"gitlab.com/gitlab-org/gitlab-workhorse/internal/testhelper" "gitlab.com/gitlab-org/gitlab-workhorse/internal/testhelper"
...@@ -60,6 +61,10 @@ func TestGetInfoRefsProxiedToGitalySuccessfully(t *testing.T) { ...@@ -60,6 +61,10 @@ func TestGetInfoRefsProxiedToGitalySuccessfully(t *testing.T) {
apiResponse := gitOkBody(t) apiResponse := gitOkBody(t)
apiResponse.GitalyServer.Address = gitalyAddress apiResponse.GitalyServer.Address = gitalyAddress
for _, showAllRefs := range []bool{true, false} {
t.Run(fmt.Sprintf("ShowAllRefs=%v", showAllRefs), func(t *testing.T) {
apiResponse.ShowAllRefs = showAllRefs
ts := testAuthServer(nil, 200, apiResponse) ts := testAuthServer(nil, 200, apiResponse)
defer ts.Close() defer ts.Close()
...@@ -69,8 +74,16 @@ func TestGetInfoRefsProxiedToGitalySuccessfully(t *testing.T) { ...@@ -69,8 +74,16 @@ func TestGetInfoRefsProxiedToGitalySuccessfully(t *testing.T) {
resource := "/gitlab-org/gitlab-test.git/info/refs?service=git-upload-pack" resource := "/gitlab-org/gitlab-test.git/info/refs?service=git-upload-pack"
_, body := httpGet(t, ws.URL+resource) _, body := httpGet(t, ws.URL+resource)
expectedContent := string(testhelper.GitalyInfoRefsResponseMock) expectedContent := "\n\000" + string(testhelper.GitalyInfoRefsResponseMock) + "\000"
if showAllRefs {
expectedContent = git.GitConfigShowAllRefs + expectedContent
}
assert.Equal(t, expectedContent, body, "GET %q: response body", resource) assert.Equal(t, expectedContent, body, "GET %q: response body", resource)
})
}
} }
func TestGetInfoRefsProxiedToGitalyInterruptedStream(t *testing.T) { func TestGetInfoRefsProxiedToGitalyInterruptedStream(t *testing.T) {
...@@ -182,11 +195,20 @@ func TestPostReceivePackProxiedToGitalyInterrupted(t *testing.T) { ...@@ -182,11 +195,20 @@ func TestPostReceivePackProxiedToGitalyInterrupted(t *testing.T) {
} }
func TestPostUploadPackProxiedToGitalySuccessfully(t *testing.T) { func TestPostUploadPackProxiedToGitalySuccessfully(t *testing.T) {
for i, tc := range []struct {
showAllRefs bool
code codes.Code
}{
{true, codes.OK},
{true, codes.Unavailable},
{false, codes.OK},
{false, codes.Unavailable},
} {
t.Run(fmt.Sprintf("Case %d", i), func(t *testing.T) {
apiResponse := gitOkBody(t) apiResponse := gitOkBody(t)
apiResponse.ShowAllRefs = tc.showAllRefs
for _, code := range []codes.Code{codes.OK, codes.Unavailable} { gitalyServer, socketPath := startGitalyServer(t, tc.code)
func() {
gitalyServer, socketPath := startGitalyServer(t, code)
defer gitalyServer.Stop() defer gitalyServer.Stop()
apiResponse.GitalyServer.Address = "unix://" + socketPath apiResponse.GitalyServer.Address = "unix://" + socketPath
...@@ -204,16 +226,23 @@ func TestPostUploadPackProxiedToGitalySuccessfully(t *testing.T) { ...@@ -204,16 +226,23 @@ func TestPostUploadPackProxiedToGitalySuccessfully(t *testing.T) {
testhelper.GitalyUploadPackResponseMock, testhelper.GitalyUploadPackResponseMock,
) )
expectedBody := strings.Join([]string{ expectedBodyParts := []string{
apiResponse.Repository.StorageName, apiResponse.Repository.StorageName,
apiResponse.Repository.RelativePath, apiResponse.Repository.RelativePath,
string(testhelper.GitalyUploadPackResponseMock), }
}, "\000") if tc.showAllRefs {
expectedBodyParts = append(expectedBodyParts, git.GitConfigShowAllRefs+"\n")
} else {
expectedBodyParts = append(expectedBodyParts, "\n")
}
expectedBodyParts = append(expectedBodyParts, string(testhelper.GitalyUploadPackResponseMock))
expectedBody := strings.Join(expectedBodyParts, "\000")
assert.Equal(t, 200, resp.StatusCode, "POST %q", resource) assert.Equal(t, 200, resp.StatusCode, "POST %q", resource)
assert.Equal(t, expectedBody, body, "POST %q: response body", resource) assert.Equal(t, expectedBody, body, "POST %q: response body", resource)
testhelper.AssertResponseHeader(t, resp, "Content-Type", "application/x-git-upload-pack-result") testhelper.AssertResponseHeader(t, resp, "Content-Type", "application/x-git-upload-pack-result")
}() })
} }
} }
......
...@@ -114,6 +114,8 @@ type Response struct { ...@@ -114,6 +114,8 @@ type Response struct {
// Repository object for making gRPC requests to Gitaly. This will // Repository object for making gRPC requests to Gitaly. This will
// eventually replace the RepoPath field. // eventually replace the RepoPath field.
Repository pb.Repository Repository pb.Repository
// For git-http, does the requestor have the right to view all refs?
ShowAllRefs bool
} }
// singleJoiningSlash is taken from reverseproxy.go:NewSingleHostReverseProxy // singleJoiningSlash is taken from reverseproxy.go:NewSingleHostReverseProxy
......
...@@ -20,6 +20,12 @@ import ( ...@@ -20,6 +20,12 @@ import (
"gitlab.com/gitlab-org/gitlab-workhorse/internal/helper" "gitlab.com/gitlab-org/gitlab-workhorse/internal/helper"
) )
const (
// We have to use a negative transfer.hideRefs since this is the only way
// to undo an already set parameter: https://www.spinics.net/lists/git/msg256772.html
GitConfigShowAllRefs = "transfer.hideRefs=!refs"
)
func ReceivePack(a *api.API) http.Handler { func ReceivePack(a *api.API) http.Handler {
return postRPCHandler(a, "handleReceivePack", handleReceivePack) return postRPCHandler(a, "handleReceivePack", handleReceivePack)
} }
...@@ -28,6 +34,16 @@ func UploadPack(a *api.API) http.Handler { ...@@ -28,6 +34,16 @@ func UploadPack(a *api.API) http.Handler {
return postRPCHandler(a, "handleUploadPack", handleUploadPack) return postRPCHandler(a, "handleUploadPack", handleUploadPack)
} }
func gitConfigOptions(a *api.Response) []string {
var out []string
if a.ShowAllRefs {
out = append(out, GitConfigShowAllRefs)
}
return out
}
func postRPCHandler(a *api.API, name string, handler func(*GitHttpResponseWriter, *http.Request, *api.Response) error) http.Handler { func postRPCHandler(a *api.API, name string, handler func(*GitHttpResponseWriter, *http.Request, *api.Response) error) http.Handler {
return repoPreAuthorizeHandler(a, func(rw http.ResponseWriter, r *http.Request, ar *api.Response) { return repoPreAuthorizeHandler(a, func(rw http.ResponseWriter, r *http.Request, ar *api.Response) {
cr := &countReadCloser{ReadCloser: r.Body} cr := &countReadCloser{ReadCloser: r.Body}
......
...@@ -77,7 +77,7 @@ func handleGetInfoRefsWithGitaly(ctx context.Context, w http.ResponseWriter, a * ...@@ -77,7 +77,7 @@ func handleGetInfoRefsWithGitaly(ctx context.Context, w http.ResponseWriter, a *
return fmt.Errorf("GetInfoRefsHandler: %v", err) return fmt.Errorf("GetInfoRefsHandler: %v", err)
} }
infoRefsResponseReader, err := smarthttp.InfoRefsResponseReader(ctx, &a.Repository, rpc) infoRefsResponseReader, err := smarthttp.InfoRefsResponseReader(ctx, &a.Repository, rpc, gitConfigOptions(a))
if err != nil { if err != nil {
return fmt.Errorf("GetInfoRefsHandler: %v", err) return fmt.Errorf("GetInfoRefsHandler: %v", err)
} }
......
...@@ -65,7 +65,7 @@ func handleUploadPackWithGitaly(ctx context.Context, a *api.Response, clientRequ ...@@ -65,7 +65,7 @@ func handleUploadPackWithGitaly(ctx context.Context, a *api.Response, clientRequ
return fmt.Errorf("smarthttp.UploadPack: %v", err) return fmt.Errorf("smarthttp.UploadPack: %v", err)
} }
if err := smarthttp.UploadPack(ctx, &a.Repository, clientRequest, clientResponse); err != nil { if err := smarthttp.UploadPack(ctx, &a.Repository, clientRequest, clientResponse, gitConfigOptions(a)); err != nil {
return fmt.Errorf("smarthttp.UploadPack: %v", err) return fmt.Errorf("smarthttp.UploadPack: %v", err)
} }
......
...@@ -13,8 +13,8 @@ type SmartHTTPClient struct { ...@@ -13,8 +13,8 @@ type SmartHTTPClient struct {
pb.SmartHTTPServiceClient pb.SmartHTTPServiceClient
} }
func (client *SmartHTTPClient) InfoRefsResponseReader(ctx context.Context, repo *pb.Repository, rpc string) (io.Reader, error) { func (client *SmartHTTPClient) InfoRefsResponseReader(ctx context.Context, repo *pb.Repository, rpc string, gitConfigOptions []string) (io.Reader, error) {
rpcRequest := &pb.InfoRefsRequest{Repository: repo} rpcRequest := &pb.InfoRefsRequest{Repository: repo, GitConfigOptions: gitConfigOptions}
switch rpc { switch rpc {
case "git-upload-pack": case "git-upload-pack":
...@@ -86,7 +86,7 @@ func (client *SmartHTTPClient) ReceivePack(ctx context.Context, repo *pb.Reposit ...@@ -86,7 +86,7 @@ func (client *SmartHTTPClient) ReceivePack(ctx context.Context, repo *pb.Reposit
return nil return nil
} }
func (client *SmartHTTPClient) UploadPack(ctx context.Context, repo *pb.Repository, clientRequest io.Reader, clientResponse io.Writer) error { func (client *SmartHTTPClient) UploadPack(ctx context.Context, repo *pb.Repository, clientRequest io.Reader, clientResponse io.Writer, gitConfigOptions []string) error {
stream, err := client.PostUploadPack(ctx) stream, err := client.PostUploadPack(ctx)
if err != nil { if err != nil {
return err return err
...@@ -94,6 +94,7 @@ func (client *SmartHTTPClient) UploadPack(ctx context.Context, repo *pb.Reposito ...@@ -94,6 +94,7 @@ func (client *SmartHTTPClient) UploadPack(ctx context.Context, repo *pb.Reposito
rpcRequest := &pb.PostUploadPackRequest{ rpcRequest := &pb.PostUploadPackRequest{
Repository: repo, Repository: repo,
GitConfigOptions: gitConfigOptions,
} }
if err := stream.Send(rpcRequest); err != nil { if err := stream.Send(rpcRequest); err != nil {
......
...@@ -53,7 +53,14 @@ func (s *GitalyTestServer) InfoRefsUploadPack(in *pb.InfoRefsRequest, stream pb. ...@@ -53,7 +53,14 @@ func (s *GitalyTestServer) InfoRefsUploadPack(in *pb.InfoRefsRequest, stream pb.
return err return err
} }
nSends, err := sendBytes([]byte(GitalyInfoRefsResponseMock), 100, func(p []byte) error { fmt.Printf("Result: %+v", in)
data := []byte(strings.Join([]string{
strings.Join(in.GitConfigOptions, "\n") + "\n",
GitalyInfoRefsResponseMock,
}, "\000") + "\000")
nSends, err := sendBytes(data, 100, func(p []byte) error {
return stream.Send(&pb.InfoRefsResponse{Data: p}) return stream.Send(&pb.InfoRefsResponse{Data: p})
}) })
if err != nil { if err != nil {
...@@ -147,6 +154,7 @@ func (s *GitalyTestServer) PostUploadPack(stream pb.SmartHTTPService_PostUploadP ...@@ -147,6 +154,7 @@ func (s *GitalyTestServer) PostUploadPack(stream pb.SmartHTTPService_PostUploadP
data := []byte(strings.Join([]string{ data := []byte(strings.Join([]string{
repo.GetStorageName(), repo.GetStorageName(),
repo.GetRelativePath(), repo.GetRelativePath(),
strings.Join(req.GitConfigOptions, "\n") + "\n",
}, "\000") + "\000") }, "\000") + "\000")
// The body of the request starts in the second message // The body of the request starts in the second message
...@@ -307,6 +315,10 @@ func (s *GitalyTestServer) Exists(context.Context, *pb.RepositoryExistsRequest) ...@@ -307,6 +315,10 @@ func (s *GitalyTestServer) Exists(context.Context, *pb.RepositoryExistsRequest)
return nil, nil return nil, nil
} }
func (s *GitalyTestServer) HasLocalBranches(ctx context.Context, in *pb.HasLocalBranchesRequest) (*pb.HasLocalBranchesResponse, error) {
return nil, nil
}
func (s *GitalyTestServer) CommitDelta(in *pb.CommitDeltaRequest, stream pb.DiffService_CommitDeltaServer) error { func (s *GitalyTestServer) CommitDelta(in *pb.CommitDeltaRequest, stream pb.DiffService_CommitDeltaServer) error {
return nil return nil
} }
...@@ -319,6 +331,10 @@ func (s *GitalyTestServer) CommitPatch(in *pb.CommitPatchRequest, stream pb.Diff ...@@ -319,6 +331,10 @@ func (s *GitalyTestServer) CommitPatch(in *pb.CommitPatchRequest, stream pb.Diff
return nil return nil
} }
func (s *GitalyTestServer) GetBlobs(in *pb.GetBlobsRequest, stream pb.BlobService_GetBlobsServer) error {
return nil
}
// sendBytes returns the number of times the 'sender' function was called and an error. // sendBytes returns the number of times the 'sender' function was called and an error.
func sendBytes(data []byte, chunkSize int, sender func([]byte) error) (int, error) { func sendBytes(data []byte, chunkSize int, sender func([]byte) error) (int, error) {
i := 0 i := 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment