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:
authorDouglas Barbosa Alexandre <dbalexandre@gmail.com>2018-03-28 03:56:28 +0300
committerDouglas Barbosa Alexandre <dbalexandre@gmail.com>2018-04-05 20:52:20 +0300
commitc98c99c5d0ac8d91e3966f9de1a8476f914eecaf (patch)
tree0dd80df4bf7441ddd1da41b924bf7c00af73a66b
parente48707d1354f24fe67fec5a88f1d93541ac9cae3 (diff)
Server implementation CalculateChecksum
-rw-r--r--internal/service/repository/calculate_checksum.go69
-rw-r--r--internal/service/repository/calculate_checksum_test.go84
2 files changed, 151 insertions, 2 deletions
diff --git a/internal/service/repository/calculate_checksum.go b/internal/service/repository/calculate_checksum.go
index 6f375d467..bbbe50e99 100644
--- a/internal/service/repository/calculate_checksum.go
+++ b/internal/service/repository/calculate_checksum.go
@@ -1,13 +1,78 @@
package repository
import (
- pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "bufio"
+ "crypto/sha1"
+ "encoding/hex"
+ "math/big"
+ pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/internal/command"
+ "gitlab.com/gitlab-org/gitaly/internal/git"
"gitlab.com/gitlab-org/gitaly/internal/helper"
"golang.org/x/net/context"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
)
+const blankChecksum = "0000000000000000000000000000000000000000"
+
func (s *server) CalculateChecksum(ctx context.Context, in *pb.CalculateChecksumRequest) (*pb.CalculateChecksumResponse, error) {
- return nil, helper.Unimplemented
+ repo := in.GetRepository()
+
+ _, err := helper.GetRepoPath(repo)
+ if err != nil {
+ return nil, err
+ }
+
+ args := []string{
+ "show-ref",
+ "--heads",
+ "--tags",
+ }
+
+ cmd, err := git.Command(ctx, repo, args...)
+ if err != nil {
+ if _, ok := status.FromError(err); ok {
+ return nil, err
+ }
+
+ return nil, status.Errorf(codes.Internal, "CalculateChecksum: gitCommand: %v", err)
+ }
+
+ var checksum *big.Int
+
+ scanner := bufio.NewScanner(cmd)
+ for scanner.Scan() {
+ ref := scanner.Text()
+
+ h := sha1.New()
+ h.Write([]byte(ref))
+
+ hash := hex.EncodeToString(h.Sum(nil))
+ hashIntBase16, _ := new(big.Int).SetString(hash, 16)
+
+ if checksum == nil {
+ checksum = hashIntBase16
+ } else {
+ checksum.Xor(checksum, hashIntBase16)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return nil, status.Errorf(codes.Internal, err.Error())
+ }
+
+ if err := cmd.Wait(); err != nil {
+ if code, ok := command.ExitStatus(err); ok && code == 1 {
+ // Exit code 1: the repository doesn't have any ref
+ return &pb.CalculateChecksumResponse{Checksum: blankChecksum}, nil
+ }
+
+ // This will normally occur when exit code > 1
+ return nil, status.Errorf(codes.Internal, err.Error())
+ }
+
+ return &pb.CalculateChecksumResponse{Checksum: hex.EncodeToString(checksum.Bytes())}, nil
}
diff --git a/internal/service/repository/calculate_checksum_test.go b/internal/service/repository/calculate_checksum_test.go
new file mode 100644
index 000000000..421dde8cd
--- /dev/null
+++ b/internal/service/repository/calculate_checksum_test.go
@@ -0,0 +1,84 @@
+package repository
+
+import (
+ "testing"
+
+ pb "gitlab.com/gitlab-org/gitaly-proto/go"
+ "gitlab.com/gitlab-org/gitaly/internal/testhelper"
+ "google.golang.org/grpc/codes"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestSuccessfulCalculateChecksum(t *testing.T) {
+ server, serverSocketPath := runRepoServer(t)
+ defer server.Stop()
+
+ client, conn := newRepositoryClient(t, serverSocketPath)
+ defer conn.Close()
+
+ testRepo, _, cleanupFn := testhelper.NewTestRepo(t)
+ defer cleanupFn()
+
+ request := &pb.CalculateChecksumRequest{Repository: testRepo}
+ testCtx, cancelCtx := testhelper.Context()
+ defer cancelCtx()
+
+ response, err := client.CalculateChecksum(testCtx, request)
+ require.NoError(t, err)
+ require.Equal(t, "8786527b0747d37d268adc75c5e5e54f3323891c", response.Checksum)
+}
+
+func TestEmptyRepositoryCalculateChecksum(t *testing.T) {
+ server, serverSocketPath := runRepoServer(t)
+ defer server.Stop()
+
+ client, conn := newRepositoryClient(t, serverSocketPath)
+ defer conn.Close()
+
+ repo, _, cleanupFn := testhelper.InitBareRepo(t)
+ defer cleanupFn()
+
+ request := &pb.CalculateChecksumRequest{Repository: repo}
+ testCtx, cancelCtx := testhelper.Context()
+ defer cancelCtx()
+
+ response, err := client.CalculateChecksum(testCtx, request)
+ require.NoError(t, err)
+ require.Equal(t, "0000000000000000000000000000000000000000", response.Checksum)
+}
+
+func TestFailedCalculateChecksum(t *testing.T) {
+ server, serverSocketPath := runRepoServer(t)
+ defer server.Stop()
+
+ client, conn := newRepositoryClient(t, serverSocketPath)
+ defer conn.Close()
+
+ invalidRepo := &pb.Repository{StorageName: "fake", RelativePath: "path"}
+
+ testCases := []struct {
+ desc string
+ request *pb.CalculateChecksumRequest
+ code codes.Code
+ }{
+ {
+ desc: "Invalid repository",
+ request: &pb.CalculateChecksumRequest{Repository: invalidRepo},
+ code: codes.InvalidArgument,
+ },
+ {
+ desc: "Repository is nil",
+ request: &pb.CalculateChecksumRequest{},
+ code: codes.InvalidArgument,
+ },
+ }
+
+ for _, testCase := range testCases {
+ testCtx, cancelCtx := testhelper.Context()
+ defer cancelCtx()
+
+ _, err := client.CalculateChecksum(testCtx, testCase.request)
+ testhelper.AssertGrpcError(t, err, testCase.code, "")
+ }
+}