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:
authorJacob Vosmaer (GitLab) <jacob@gitlab.com>2017-09-22 15:56:31 +0300
committerAhmad Sherif <ahmad.m.sherif@gmail.com>2017-09-22 15:56:31 +0300
commitd53cbe09cad0ee227e24f2af36b7caac1dccc0d6 (patch)
treeeb60824bd9b2cfa6b9921a105c7ffdd8a7cd108d
parentf220038f1f46291d2eea829665ae205111573fff (diff)
Implement CreateRepository
-rw-r--r--CHANGELOG.md2
-rw-r--r--internal/rubyserver/rubyserver.go22
-rw-r--r--internal/rubyserver/rubyserver_test.go4
-rw-r--r--internal/service/commit/stats.go8
-rw-r--r--internal/service/register.go3
-rw-r--r--internal/service/repository/create.go22
-rw-r--r--internal/service/repository/create_test.go84
-rw-r--r--internal/service/repository/server.go17
-rw-r--r--internal/service/repository/testdata/gitlab-shell/hooks/.gitkeep0
-rw-r--r--internal/service/repository/testhelper_test.go31
-rw-r--r--ruby/lib/gitaly_server.rb2
-rw-r--r--ruby/lib/gitaly_server/repository_service.rb12
-rw-r--r--ruby/lib/gitlab/git.rb14
13 files changed, 199 insertions, 22 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index da4fd7b1f..2da2d8dd5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@ UNRELEASED
https://gitlab.com/gitlab-org/gitaly/merge_requests/360
- Implement UserDeleteTag RPC
https://gitlab.com/gitlab-org/gitaly/merge_requests/366
+- Implement RepositoryService::CreateRepository
+ https://gitlab.com/gitlab-org/gitaly/merge_requests/361
v0.40.0
- Use context cancellation instead of command.Close
diff --git a/internal/rubyserver/rubyserver.go b/internal/rubyserver/rubyserver.go
index 3db51ea92..0470019b2 100644
--- a/internal/rubyserver/rubyserver.go
+++ b/internal/rubyserver/rubyserver.go
@@ -97,10 +97,16 @@ func (s *Server) Stop() {
func Start() (*Server, error) {
lazyInit.Do(prepareSocketPath)
+ cfg := config.Config
+ env := []string{
+ "GITALY_RUBY_GIT_BIN_PATH=" + command.GitPath(),
+ fmt.Sprintf("GITALY_RUBY_WRITE_BUFFER_SIZE=%d", streamio.WriteBufferSize),
+ "GITALY_RUBY_GITLAB_SHELL_PATH=" + cfg.GitlabShell.Dir,
+ }
+
args := []string{"bundle", "exec", "bin/gitaly-ruby", fmt.Sprintf("%d", os.Getpid()), socketPath()}
- env := append(os.Environ(), "GITALY_RUBY_GIT_BIN_PATH="+command.GitPath(),
- fmt.Sprintf("GITALY_RUBY_WRITE_BUFFER_SIZE=%d", streamio.WriteBufferSize))
- p, err := supervisor.New("gitaly-ruby", env, args, config.Config.Ruby.Dir)
+
+ p, err := supervisor.New("gitaly-ruby", append(os.Environ(), env...), args, cfg.Ruby.Dir)
return &Server{Process: p}, err
}
@@ -136,6 +142,14 @@ func (s *Server) OperationServiceClient(ctx context.Context) (pb.OperationServic
return pb.NewOperationServiceClient(conn), err
}
+// RepositoryServiceClient returns a RefServiceClient instance that is
+// configured to connect to the running Ruby server. This assumes Start()
+// has been called already.
+func (s *Server) RepositoryServiceClient(ctx context.Context) (pb.RepositoryServiceClient, error) {
+ conn, err := s.getConnection(ctx)
+ return pb.NewRepositoryServiceClient(conn), err
+}
+
func (s *Server) getConnection(ctx context.Context) (*grpc.ClientConn, error) {
s.clientConnMu.RLock()
conn := s.clientConn
@@ -180,7 +194,7 @@ func dialOptions() []grpc.DialOption {
// SetHeaders adds headers that tell gitaly-ruby the full path to the repository.
func SetHeaders(ctx context.Context, repo *pb.Repository) (context.Context, error) {
- repoPath, err := helper.GetRepoPath(repo)
+ repoPath, err := helper.GetPath(repo)
if err != nil {
return nil, err
}
diff --git a/internal/rubyserver/rubyserver_test.go b/internal/rubyserver/rubyserver_test.go
index cb3dfd1e2..c39782d3b 100644
--- a/internal/rubyserver/rubyserver_test.go
+++ b/internal/rubyserver/rubyserver_test.go
@@ -34,10 +34,6 @@ func TestSetHeaders(t *testing.T) {
errType: codes.InvalidArgument,
},
{
- repo: &pb.Repository{StorageName: testRepo.GetStorageName(), RelativePath: "bar.git"},
- errType: codes.NotFound,
- },
- {
repo: testRepo,
errType: codes.OK,
},
diff --git a/internal/service/commit/stats.go b/internal/service/commit/stats.go
index 6c5efd335..9b647f15b 100644
--- a/internal/service/commit/stats.go
+++ b/internal/service/commit/stats.go
@@ -4,6 +4,7 @@ import (
"golang.org/x/net/context"
pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/internal/helper"
"gitlab.com/gitlab-org/gitaly/internal/rubyserver"
)
@@ -13,7 +14,12 @@ func (s *server) CommitStats(ctx context.Context, in *pb.CommitStatsRequest) (*p
return nil, err
}
- clientCtx, err := rubyserver.SetHeaders(ctx, in.GetRepository())
+ repo := in.GetRepository()
+ if _, err := helper.GetRepoPath(repo); err != nil {
+ return nil, err
+ }
+
+ clientCtx, err := rubyserver.SetHeaders(ctx, repo)
if err != nil {
return nil, err
}
diff --git a/internal/service/register.go b/internal/service/register.go
index fe2636c6b..cfdd93584 100644
--- a/internal/service/register.go
+++ b/internal/service/register.go
@@ -44,8 +44,7 @@ func RegisterAll(grpcServer *grpc.Server, rubyServer *rubyserver.Server) {
blobService := blob.NewServer()
pb.RegisterBlobServiceServer(grpcServer, blobService)
- repositoryService := repository.NewServer()
- pb.RegisterRepositoryServiceServer(grpcServer, repositoryService)
+ pb.RegisterRepositoryServiceServer(grpcServer, repository.NewServer(rubyServer))
namespaceService := namespace.NewServer()
pb.RegisterNamespaceServiceServer(grpcServer, namespaceService)
diff --git a/internal/service/repository/create.go b/internal/service/repository/create.go
new file mode 100644
index 000000000..65ecd63b2
--- /dev/null
+++ b/internal/service/repository/create.go
@@ -0,0 +1,22 @@
+package repository
+
+import (
+ pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/internal/rubyserver"
+
+ "golang.org/x/net/context"
+)
+
+func (s *server) CreateRepository(ctx context.Context, req *pb.CreateRepositoryRequest) (*pb.CreateRepositoryResponse, error) {
+ client, err := s.RepositoryServiceClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ clientCtx, err := rubyserver.SetHeaders(ctx, req.GetRepository())
+ if err != nil {
+ return nil, err
+ }
+
+ return client.CreateRepository(clientCtx, req)
+}
diff --git a/internal/service/repository/create_test.go b/internal/service/repository/create_test.go
new file mode 100644
index 000000000..81fa71274
--- /dev/null
+++ b/internal/service/repository/create_test.go
@@ -0,0 +1,84 @@
+package repository
+
+import (
+ "fmt"
+ "os"
+ "path"
+ "testing"
+
+ pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/internal/config"
+ "gitlab.com/gitlab-org/gitaly/internal/helper"
+ "gitlab.com/gitlab-org/gitaly/internal/testhelper"
+
+ "github.com/stretchr/testify/require"
+ "google.golang.org/grpc/codes"
+)
+
+func TestCreateRepositorySuccess(t *testing.T) {
+ server := runRepoServer(t)
+ defer server.Stop()
+
+ client, conn := newRepositoryClient(t)
+ defer conn.Close()
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ storageDir, err := helper.GetStorageByName("default")
+ require.NoError(t, err)
+ relativePath := "create-repository-test.git"
+ repoDir := path.Join(storageDir, relativePath)
+ require.NoError(t, os.RemoveAll(repoDir))
+
+ repo := &pb.Repository{StorageName: "default", RelativePath: relativePath}
+ req := &pb.CreateRepositoryRequest{Repository: repo}
+ _, err = client.CreateRepository(ctx, req)
+ require.NoError(t, err)
+
+ for _, dir := range []string{repoDir, path.Join(repoDir, "refs")} {
+ fi, err := os.Stat(dir)
+ require.NoError(t, err)
+ require.True(t, fi.IsDir(), "%q must be a directory", fi.Name())
+ }
+
+ hooksDir := path.Join(repoDir, "hooks")
+
+ fi, err := os.Lstat(hooksDir)
+ require.NoError(t, err)
+ require.True(t, fi.Mode()&os.ModeSymlink > 0, "expected %q to be a symlink, got mode %v", hooksDir, fi.Mode())
+
+ hooksTarget, err := os.Readlink(hooksDir)
+ require.NoError(t, err)
+ require.Equal(t, path.Join(config.Config.GitlabShell.Dir, "hooks"), hooksTarget)
+}
+
+func TestCreateRepositoryFailure(t *testing.T) {
+ server := runRepoServer(t)
+ defer server.Stop()
+
+ client, conn := newRepositoryClient(t)
+ defer conn.Close()
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ testCases := []struct {
+ repo *pb.Repository
+ code codes.Code
+ }{
+ {
+ repo: &pb.Repository{StorageName: "does not exist", RelativePath: "foobar.git"},
+ code: codes.InvalidArgument,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(fmt.Sprintf("%+v", tc.repo), func(t *testing.T) {
+ _, err := client.CreateRepository(ctx, &pb.CreateRepositoryRequest{Repository: tc.repo})
+
+ require.Error(t, err)
+ testhelper.AssertGrpcError(t, err, tc.code, "")
+ })
+ }
+}
diff --git a/internal/service/repository/server.go b/internal/service/repository/server.go
index 0ad70bc7e..13d859902 100644
--- a/internal/service/repository/server.go
+++ b/internal/service/repository/server.go
@@ -1,19 +1,16 @@
package repository
import (
- pb "gitlab.com/gitlab-org/gitaly-proto/go"
- "gitlab.com/gitlab-org/gitaly/internal/helper"
+ "gitlab.com/gitlab-org/gitaly/internal/rubyserver"
- "golang.org/x/net/context"
+ pb "gitlab.com/gitlab-org/gitaly-proto/go"
)
-type server struct{}
-
-// NewServer creates a new instance of a gRPC repo server
-func NewServer() pb.RepositoryServiceServer {
- return &server{}
+type server struct {
+ *rubyserver.Server
}
-func (*server) CreateRepository(context.Context, *pb.CreateRepositoryRequest) (*pb.CreateRepositoryResponse, error) {
- return nil, helper.Unimplemented
+// NewServer creates a new instance of a gRPC repo server
+func NewServer(rs *rubyserver.Server) pb.RepositoryServiceServer {
+ return &server{rs}
}
diff --git a/internal/service/repository/testdata/gitlab-shell/hooks/.gitkeep b/internal/service/repository/testdata/gitlab-shell/hooks/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/internal/service/repository/testdata/gitlab-shell/hooks/.gitkeep
diff --git a/internal/service/repository/testhelper_test.go b/internal/service/repository/testhelper_test.go
index 536645eae..824f5c083 100644
--- a/internal/service/repository/testhelper_test.go
+++ b/internal/service/repository/testhelper_test.go
@@ -1,13 +1,17 @@
package repository
import (
+ "log"
"net"
"os"
+ "path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/internal/config"
+ "gitlab.com/gitlab-org/gitaly/internal/rubyserver"
"gitlab.com/gitlab-org/gitaly/internal/testhelper"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
@@ -20,6 +24,7 @@ var (
testTime = time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)
serverSocketPath = testhelper.GetTemporaryGitalySocketFileName()
testRepo = testhelper.TestRepository()
+ rubyServer *rubyserver.Server
)
func newRepositoryClient(t *testing.T) (pb.RepositoryServiceClient, *grpc.ClientConn) {
@@ -44,7 +49,7 @@ func runRepoServer(t *testing.T) *grpc.Server {
t.Fatal(err)
}
- pb.RegisterRepositoryServiceServer(server, NewServer())
+ pb.RegisterRepositoryServiceServer(server, NewServer(rubyServer))
reflection.Register(server)
go server.Serve(listener)
@@ -66,3 +71,27 @@ func assertModTimeAfter(t *testing.T, afterTime time.Time, paths ...string) bool
}
return t.Failed()
}
+
+func TestMain(m *testing.M) {
+ os.Exit(testMain(m))
+}
+
+func testMain(m *testing.M) int {
+ defer testhelper.MustHaveNoChildProcess()
+
+ testhelper.ConfigureRuby()
+
+ var err error
+ config.Config.GitlabShell.Dir, err = filepath.Abs("testdata/gitlab-shell")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ rubyServer, err = rubyserver.Start()
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer rubyServer.Stop()
+
+ return m.Run()
+}
diff --git a/ruby/lib/gitaly_server.rb b/ruby/lib/gitaly_server.rb
index deaea16c4..52e744bfd 100644
--- a/ruby/lib/gitaly_server.rb
+++ b/ruby/lib/gitaly_server.rb
@@ -7,6 +7,7 @@ require_relative 'gitaly_server/commit_service.rb'
require_relative 'gitaly_server/diff_service.rb'
require_relative 'gitaly_server/ref_service.rb'
require_relative 'gitaly_server/operations_service.rb'
+require_relative 'gitaly_server/repository_service.rb'
module GitalyServer
REPO_PATH_HEADER = 'gitaly-repo-path'.freeze
@@ -20,5 +21,6 @@ module GitalyServer
server.handle(DiffService.new)
server.handle(RefService.new)
server.handle(OperationsService.new)
+ server.handle(RepositoryService.new)
end
end
diff --git a/ruby/lib/gitaly_server/repository_service.rb b/ruby/lib/gitaly_server/repository_service.rb
new file mode 100644
index 000000000..8006ddd6a
--- /dev/null
+++ b/ruby/lib/gitaly_server/repository_service.rb
@@ -0,0 +1,12 @@
+module GitalyServer
+ class RepositoryService < Gitaly::RepositoryService::Service
+ def create_repository(request, _call)
+ repo_path = GitalyServer.repo_path(_call)
+
+ # TODO refactor Repository.create to eliminate bogus '/' argument
+ Gitlab::Git::Repository.create('/', repo_path, bare: true, symlink_hooks_to: Gitlab.config.gitlab_shell.hooks_path)
+
+ Gitaly::CreateRepositoryResponse.new
+ end
+ end
+end
diff --git a/ruby/lib/gitlab/git.rb b/ruby/lib/gitlab/git.rb
index de57cd81b..fca45d316 100644
--- a/ruby/lib/gitlab/git.rb
+++ b/ruby/lib/gitlab/git.rb
@@ -38,9 +38,23 @@ module Gitlab
end
end
+ class GitlabShell
+ def path
+ ENV['GITALY_RUBY_GITLAB_SHELL_PATH']
+ end
+
+ def hooks_path
+ File.join(path, 'hooks')
+ end
+ end
+
def git
Git.new
end
+
+ def gitlab_shell
+ GitlabShell.new
+ end
end
def self.config