From 462598daa8a0ef5a150abfc4121c44b31ce23b11 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Tue, 19 Dec 2017 14:05:33 +0100 Subject: Implement ListBlobsByRevisionPath --- CHANGELOG.md | 2 + .../service/blob/list_blobs_by_revision_paths.go | 132 +++++++++++++ .../blob/list_blobs_by_revision_paths_test.go | 155 +++++++++++++++ .../gitlab-org/gitaly-proto/go/blob.pb.go | 207 +++++++++++++++++++-- vendor/vendor.json | 8 +- 5 files changed, 481 insertions(+), 23 deletions(-) create mode 100644 internal/service/blob/list_blobs_by_revision_paths.go create mode 100644 internal/service/blob/list_blobs_by_revision_paths_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index a3707670a..c6451b612 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ UNRELEASED +- Implement ListBlobsByRevisionPath + https://gitlab.com/gitlab-org/gitaly/merge_requests/499 - Update vendored gitlab_git to 31fa9313991881258b4697cb507cfc8ab205b7dc https://gitlab.com/gitlab-org/gitaly/merge_requests/486 diff --git a/internal/service/blob/list_blobs_by_revision_paths.go b/internal/service/blob/list_blobs_by_revision_paths.go new file mode 100644 index 000000000..a86d01aaf --- /dev/null +++ b/internal/service/blob/list_blobs_by_revision_paths.go @@ -0,0 +1,132 @@ +package blob + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "os/exec" + "strings" + + 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/git/catfile" + "gitlab.com/gitlab-org/gitaly/internal/helper" + "gitlab.com/gitlab-org/gitaly/streamio" + + "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus" + "golang.org/x/net/context" +) + +// BatchBlobMaxReadLimit sets the limit for the data in messages when performing +// a batch request +const BatchBlobMaxReadLimit = 1 << 20 + +// For batch blobs fetching by revision path, for example, for commit +// abcdef1234 give me CHANGELOG. Given its a batch endpoint we limit the +// response size to BatchBlobMaxReadLimit. Errors are logged, but for clients +// not visible, unless the repository can't be found. If #input != #output that +// means that either the item was not found or an internal error occured. It is +// the responsibilty of the client to gracefully handle these cases. +func (s *server) ListBlobsByRevisionPath(in *pb.ListBlobsByRevisionPathRequest, stream pb.BlobService_ListBlobsByRevisionPathServer) error { + repoPath, err := helper.GetRepoPath(in.Repository) + if err != nil { + return err + } + + for _, revisionPath := range in.RevisionPaths { + revision := revisionPath.GetCommitOid() + path := revisionPath.GetPath() + limit := readLimit(revisionPath.Limit) + if revision == "" || path == "" { + continue + } + + blobOid, err := lookupRevision(stream.Context(), in.Repository, fmt.Sprintf("%s:%s", revision, path)) + if err != nil { + grpc_logrus.Extract(stream.Context()).WithError(err) + continue + } + + if err := sendBlobMsg(stream, repoPath, blobOid, limit); err != nil { + grpc_logrus.Extract(stream.Context()).WithError(err) + } + } + + return nil +} + +func sendBlobMsg(stream pb.BlobService_ListBlobsByRevisionPathServer, repoPath, oid string, limit int64) error { + stdinReader, stdinWriter := io.Pipe() + + cmdArgs := []string{"--git-dir", repoPath, "cat-file", "--batch"} + cmd, err := command.New(stream.Context(), exec.Command(command.GitPath(), cmdArgs...), stdinReader, nil, nil) + if err != nil { + return fmt.Errorf("ListBlobsByRevisionPath: cmd: %v", err) + } + defer stdinWriter.Close() + defer stdinReader.Close() + + if _, err := fmt.Fprintln(stdinWriter, oid); err != nil { + return fmt.Errorf("ListBlobsByRevisionPath: stdin write: %v", err) + } + stdinWriter.Close() + + stdout := bufio.NewReader(cmd) + + objectInfo, err := catfile.ParseObjectInfo(stdout) + if err != nil { + return fmt.Errorf("ListCommitsByOid: %v", err) + } + if objectInfo.Type != "blob" { + return fmt.Errorf("ListCommitsByOid: expected type blob, found: %s", objectInfo.Type) + } + + sw := streamio.NewWriter(func(p []byte) error { + msg := &pb.ListBlobsByRevisionPathResponse{ + Oid: objectInfo.Oid, + Size: objectInfo.Size, + Data: p, + } + return stream.Send(msg) + }) + + n, err := io.Copy(sw, io.LimitReader(stdout, limit)) + if err != nil { + return fmt.Errorf("ListBlobsByRevisionPath: send: %v", err) + } + if n != limit { + return fmt.Errorf("ListBlobsByRevisionPath: short send: %d/%d bytes", n, objectInfo.Size) + } + + return nil +} + +// Copied from `internal/service/commit/languages.go` +// TODO consider making a plumbing lib and put it there +func lookupRevision(ctx context.Context, repo *pb.Repository, revision string) (string, error) { + revParse, err := git.Command(ctx, repo, "rev-parse", revision) + if err != nil { + return "", err + } + + revParseBytes, err := ioutil.ReadAll(revParse) + if err != nil { + return "", err + } + + return strings.TrimSpace(string(revParseBytes)), nil +} + +func readLimit(initialLimit int64) int64 { + if initialLimit <= 0 { + return BatchBlobMaxReadLimit + } + + if initialLimit < BatchBlobMaxReadLimit { + return initialLimit + } + + return BatchBlobMaxReadLimit +} diff --git a/internal/service/blob/list_blobs_by_revision_paths_test.go b/internal/service/blob/list_blobs_by_revision_paths_test.go new file mode 100644 index 000000000..315e31279 --- /dev/null +++ b/internal/service/blob/list_blobs_by_revision_paths_test.go @@ -0,0 +1,155 @@ +package blob + +import ( + "fmt" + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + pb "gitlab.com/gitlab-org/gitaly-proto/go" + "gitlab.com/gitlab-org/gitaly/internal/testhelper" + "golang.org/x/net/context" +) + +func TestListBlobsByRevisionPath(t *testing.T) { + server, serverSocketPath := runBlobServer(t) + defer server.Stop() + + testRepo, _, cleanupFn := testhelper.NewTestRepo(t) + defer cleanupFn() + + client, conn := newBlobClient(t, serverSocketPath) + defer conn.Close() + + testCases := []struct { + path string + oid string + limit int64 + size int64 + blobOid string + notFound bool + }{ + { + path: "", + oid: "e63f41fe459e62e1228fcef60d7189127aeba95a", + }, + { + path: "CHANGELOG", + oid: "e63f41fe459e62e1228fcef60d7189127aeba95a", + blobOid: "53855584db773c3df5b5f61f72974cb298822fbb", + limit: 1, + }, + { + path: "CHANGELOG", + oid: "e63f41fe459e62e1228fcef60d7189127aeba95a", + blobOid: "53855584db773c3df5b5f61f72974cb298822fbb", + limit: -1, + }, + { + path: "bar/branch-test.txt", + oid: "e63f41fe459e62e1228fcef60d7189127aeba95a", + blobOid: "93e123ac8a3e6a0b600953d7598af629dec7b735", + limit: 100, + }, + { + path: "bar/branch-test.txt", + oid: "", + limit: 100, + }, + } + + var revPaths []*pb.ListBlobsByRevisionPathRequest_RevisionPath + for _, tc := range testCases { + revPath := pb.ListBlobsByRevisionPathRequest_RevisionPath{ + CommitOid: tc.oid, + Path: tc.path, + Limit: tc.limit, + } + + revPaths = append(revPaths, &revPath) + } + + request := &pb.ListBlobsByRevisionPathRequest{ + Repository: testRepo, + RevisionPaths: revPaths, + } + + ctx, cancel := testhelper.Context() + defer cancel() + + stream, err := client.ListBlobsByRevisionPath(ctx, request) + require.NoError(t, err) + + var blobs []*pb.ListBlobsByRevisionPathResponse + for { + blob, err := stream.Recv() + if err != io.EOF { + break + } + + require.NoError(t, err) + blobs = append(blobs, blob) + } + + // It excludes unfound examples + assert.Len(t, blobs, 3) + + // Cross check + for _, blob := range blobs { + resp, err := client.GetBlob(ctx, &pb.GetBlobRequest{testRepo, blob.Oid, blob.Size}) + require.NoError(t, err) + + msg, err := resp.Recv() + require.NoError(t, err) + + assert.Equal(t, msg.Data, blob.Data) + assert.Equal(t, msg.Size, blob.Size) + assert.Equal(t, msg.Oid, blob.Oid) + } +} + +func TestLookupRevision(t *testing.T) { + testRepo, _, cleanupFn := testhelper.NewTestRepo(t) + defer cleanupFn() + + testCases := []struct { + path string + oid string + blobOid string + }{ + { + path: "CHANGELOG", + oid: "e63f41fe459e62e1228fcef60d7189127aeba95a", + blobOid: "53855584db773c3df5b5f61f72974cb298822fbb", + }, + { + path: "bar/branch-test.txt", + oid: "e63f41fe459e62e1228fcef60d7189127aeba95a", + blobOid: "93e123ac8a3e6a0b600953d7598af629dec7b735", + }, + } + + for _, tc := range testCases { + // Context not needed here, so passing in a mock + oid, err := lookupRevision(context.TODO(), testRepo, fmt.Sprintf("%s:%s", tc.oid, tc.path)) + assert.NoError(t, err) + assert.Equal(t, tc.blobOid, oid) + } +} + +func TestReadLimit(t *testing.T) { + testCase := []struct { + input int64 + output int64 + }{ + {1, 1}, + {-1, BatchBlobMaxReadLimit}, + {0, BatchBlobMaxReadLimit}, + {1 << 21, BatchBlobMaxReadLimit}, + } + + for _, tc := range testCase { + assert.Equal(t, tc.output, readLimit(tc.input)) + } +} diff --git a/vendor/gitlab.com/gitlab-org/gitaly-proto/go/blob.pb.go b/vendor/gitlab.com/gitlab-org/gitaly-proto/go/blob.pb.go index 223e17e09..d986472a8 100644 --- a/vendor/gitlab.com/gitlab-org/gitaly-proto/go/blob.pb.go +++ b/vendor/gitlab.com/gitlab-org/gitaly-proto/go/blob.pb.go @@ -25,6 +25,8 @@ It has these top-level messages: GetBlobResponse GetBlobsRequest GetBlobsResponse + ListBlobsByRevisionPathRequest + ListBlobsByRevisionPathResponse CommitStatsRequest CommitStatsResponse CommitIsAncestorRequest @@ -356,11 +358,108 @@ func (m *GetBlobsResponse) GetOid() string { return "" } +type ListBlobsByRevisionPathRequest struct { + Repository *Repository `protobuf:"bytes,1,opt,name=repository" json:"repository,omitempty"` + RevisionPaths []*ListBlobsByRevisionPathRequest_RevisionPath `protobuf:"bytes,2,rep,name=revision_paths,json=revisionPaths" json:"revision_paths,omitempty"` +} + +func (m *ListBlobsByRevisionPathRequest) Reset() { *m = ListBlobsByRevisionPathRequest{} } +func (m *ListBlobsByRevisionPathRequest) String() string { return proto.CompactTextString(m) } +func (*ListBlobsByRevisionPathRequest) ProtoMessage() {} +func (*ListBlobsByRevisionPathRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *ListBlobsByRevisionPathRequest) GetRepository() *Repository { + if m != nil { + return m.Repository + } + return nil +} + +func (m *ListBlobsByRevisionPathRequest) GetRevisionPaths() []*ListBlobsByRevisionPathRequest_RevisionPath { + if m != nil { + return m.RevisionPaths + } + return nil +} + +type ListBlobsByRevisionPathRequest_RevisionPath struct { + CommitOid string `protobuf:"bytes,1,opt,name=commit_oid,json=commitOid" json:"commit_oid,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + Limit int64 `protobuf:"varint,3,opt,name=limit" json:"limit,omitempty"` +} + +func (m *ListBlobsByRevisionPathRequest_RevisionPath) Reset() { + *m = ListBlobsByRevisionPathRequest_RevisionPath{} +} +func (m *ListBlobsByRevisionPathRequest_RevisionPath) String() string { + return proto.CompactTextString(m) +} +func (*ListBlobsByRevisionPathRequest_RevisionPath) ProtoMessage() {} +func (*ListBlobsByRevisionPathRequest_RevisionPath) Descriptor() ([]byte, []int) { + return fileDescriptor0, []int{4, 0} +} + +func (m *ListBlobsByRevisionPathRequest_RevisionPath) GetCommitOid() string { + if m != nil { + return m.CommitOid + } + return "" +} + +func (m *ListBlobsByRevisionPathRequest_RevisionPath) GetPath() string { + if m != nil { + return m.Path + } + return "" +} + +func (m *ListBlobsByRevisionPathRequest_RevisionPath) GetLimit() int64 { + if m != nil { + return m.Limit + } + return 0 +} + +type ListBlobsByRevisionPathResponse struct { + Oid string `protobuf:"bytes,1,opt,name=oid" json:"oid,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Size int64 `protobuf:"varint,3,opt,name=size" json:"size,omitempty"` +} + +func (m *ListBlobsByRevisionPathResponse) Reset() { *m = ListBlobsByRevisionPathResponse{} } +func (m *ListBlobsByRevisionPathResponse) String() string { return proto.CompactTextString(m) } +func (*ListBlobsByRevisionPathResponse) ProtoMessage() {} +func (*ListBlobsByRevisionPathResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +func (m *ListBlobsByRevisionPathResponse) GetOid() string { + if m != nil { + return m.Oid + } + return "" +} + +func (m *ListBlobsByRevisionPathResponse) GetData() []byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ListBlobsByRevisionPathResponse) GetSize() int64 { + if m != nil { + return m.Size + } + return 0 +} + func init() { proto.RegisterType((*GetBlobRequest)(nil), "gitaly.GetBlobRequest") proto.RegisterType((*GetBlobResponse)(nil), "gitaly.GetBlobResponse") proto.RegisterType((*GetBlobsRequest)(nil), "gitaly.GetBlobsRequest") proto.RegisterType((*GetBlobsResponse)(nil), "gitaly.GetBlobsResponse") + proto.RegisterType((*ListBlobsByRevisionPathRequest)(nil), "gitaly.ListBlobsByRevisionPathRequest") + proto.RegisterType((*ListBlobsByRevisionPathRequest_RevisionPath)(nil), "gitaly.ListBlobsByRevisionPathRequest.RevisionPath") + proto.RegisterType((*ListBlobsByRevisionPathResponse)(nil), "gitaly.ListBlobsByRevisionPathResponse") } // Reference imports to suppress errors if they are not otherwise used. @@ -383,6 +482,9 @@ type BlobServiceClient interface { // The blobs are sent in a continous stream, the caller is responsible for spliting // them up into multiple blobs by their object IDs. GetBlobs(ctx context.Context, in *GetBlobsRequest, opts ...grpc.CallOption) (BlobService_GetBlobsClient, error) + // ListBlobsByRevisionPath returns the blob for each (commit_oid, path) passed in + // Commit oid and path can vary between each request and might not have any relation to each other + ListBlobsByRevisionPath(ctx context.Context, in *ListBlobsByRevisionPathRequest, opts ...grpc.CallOption) (BlobService_ListBlobsByRevisionPathClient, error) } type blobServiceClient struct { @@ -457,6 +559,38 @@ func (x *blobServiceGetBlobsClient) Recv() (*GetBlobsResponse, error) { return m, nil } +func (c *blobServiceClient) ListBlobsByRevisionPath(ctx context.Context, in *ListBlobsByRevisionPathRequest, opts ...grpc.CallOption) (BlobService_ListBlobsByRevisionPathClient, error) { + stream, err := grpc.NewClientStream(ctx, &_BlobService_serviceDesc.Streams[2], c.cc, "/gitaly.BlobService/ListBlobsByRevisionPath", opts...) + if err != nil { + return nil, err + } + x := &blobServiceListBlobsByRevisionPathClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type BlobService_ListBlobsByRevisionPathClient interface { + Recv() (*ListBlobsByRevisionPathResponse, error) + grpc.ClientStream +} + +type blobServiceListBlobsByRevisionPathClient struct { + grpc.ClientStream +} + +func (x *blobServiceListBlobsByRevisionPathClient) Recv() (*ListBlobsByRevisionPathResponse, error) { + m := new(ListBlobsByRevisionPathResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // Server API for BlobService service type BlobServiceServer interface { @@ -469,6 +603,9 @@ type BlobServiceServer interface { // The blobs are sent in a continous stream, the caller is responsible for spliting // them up into multiple blobs by their object IDs. GetBlobs(*GetBlobsRequest, BlobService_GetBlobsServer) error + // ListBlobsByRevisionPath returns the blob for each (commit_oid, path) passed in + // Commit oid and path can vary between each request and might not have any relation to each other + ListBlobsByRevisionPath(*ListBlobsByRevisionPathRequest, BlobService_ListBlobsByRevisionPathServer) error } func RegisterBlobServiceServer(s *grpc.Server, srv BlobServiceServer) { @@ -517,6 +654,27 @@ func (x *blobServiceGetBlobsServer) Send(m *GetBlobsResponse) error { return x.ServerStream.SendMsg(m) } +func _BlobService_ListBlobsByRevisionPath_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ListBlobsByRevisionPathRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(BlobServiceServer).ListBlobsByRevisionPath(m, &blobServiceListBlobsByRevisionPathServer{stream}) +} + +type BlobService_ListBlobsByRevisionPathServer interface { + Send(*ListBlobsByRevisionPathResponse) error + grpc.ServerStream +} + +type blobServiceListBlobsByRevisionPathServer struct { + grpc.ServerStream +} + +func (x *blobServiceListBlobsByRevisionPathServer) Send(m *ListBlobsByRevisionPathResponse) error { + return x.ServerStream.SendMsg(m) +} + var _BlobService_serviceDesc = grpc.ServiceDesc{ ServiceName: "gitaly.BlobService", HandlerType: (*BlobServiceServer)(nil), @@ -532,6 +690,11 @@ var _BlobService_serviceDesc = grpc.ServiceDesc{ Handler: _BlobService_GetBlobs_Handler, ServerStreams: true, }, + { + StreamName: "ListBlobsByRevisionPath", + Handler: _BlobService_ListBlobsByRevisionPath_Handler, + ServerStreams: true, + }, }, Metadata: "blob.proto", } @@ -539,22 +702,30 @@ var _BlobService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("blob.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 266 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0x31, 0x4f, 0xc3, 0x30, - 0x10, 0x85, 0x71, 0x5d, 0x0a, 0xbd, 0x56, 0x50, 0x9d, 0x10, 0x58, 0x99, 0xa2, 0x4c, 0x99, 0x22, - 0x14, 0x76, 0x24, 0x58, 0x18, 0x60, 0x32, 0xbf, 0x20, 0x21, 0x27, 0xb0, 0x64, 0xb8, 0x60, 0x1b, - 0xa4, 0xf2, 0x2b, 0xf8, 0xc9, 0x28, 0x0e, 0x49, 0x81, 0x8a, 0xa9, 0xdb, 0xcb, 0xbb, 0xcb, 0x7b, - 0x9f, 0x6c, 0x03, 0xd4, 0x96, 0xeb, 0xa2, 0x75, 0x1c, 0x18, 0x67, 0x8f, 0x26, 0x54, 0x76, 0x9d, - 0x2c, 0xfd, 0x53, 0xe5, 0xa8, 0xe9, 0xdd, 0xcc, 0xc2, 0xd1, 0x0d, 0x85, 0x6b, 0xcb, 0xb5, 0xa6, - 0xd7, 0x37, 0xf2, 0x01, 0x4b, 0x00, 0x47, 0x2d, 0x7b, 0x13, 0xd8, 0xad, 0x95, 0x48, 0x45, 0xbe, - 0x28, 0xb1, 0xe8, 0x7f, 0x2e, 0xf4, 0x38, 0xd1, 0x3f, 0xb6, 0x70, 0x05, 0x92, 0x4d, 0xa3, 0x26, - 0xa9, 0xc8, 0xe7, 0xba, 0x93, 0x78, 0x02, 0xfb, 0xd6, 0x3c, 0x9b, 0xa0, 0x64, 0x2a, 0x72, 0xa9, - 0xfb, 0x8f, 0xec, 0x16, 0x8e, 0xc7, 0x36, 0xdf, 0xf2, 0x8b, 0x27, 0x44, 0x98, 0x7a, 0xf3, 0x41, - 0xb1, 0x48, 0xea, 0xa8, 0x3b, 0xaf, 0xa9, 0x42, 0x15, 0xf3, 0x96, 0x3a, 0xea, 0xa1, 0x42, 0x8e, - 0x15, 0x19, 0x8f, 0x61, 0x7e, 0x17, 0x76, 0x84, 0x29, 0x9b, 0xc6, 0xab, 0x49, 0x2a, 0xf3, 0xb9, - 0x8e, 0xfa, 0x1f, 0xfa, 0x3b, 0x58, 0x6d, 0x0a, 0x77, 0xc5, 0x2f, 0x3f, 0x05, 0x2c, 0xba, 0xac, - 0x7b, 0x72, 0xef, 0xe6, 0x81, 0xf0, 0x12, 0x0e, 0xbe, 0xd3, 0xf1, 0x74, 0x40, 0xfe, 0x7d, 0x35, - 0xc9, 0xd9, 0x96, 0xdf, 0x53, 0x64, 0x7b, 0xe7, 0x02, 0xaf, 0xe0, 0x70, 0xa0, 0xc3, 0xbf, 0x8b, - 0xc3, 0x01, 0x25, 0x6a, 0x7b, 0xb0, 0x89, 0xa8, 0x67, 0xf1, 0x4d, 0x5c, 0x7c, 0x05, 0x00, 0x00, - 0xff, 0xff, 0x99, 0x07, 0x5e, 0x8d, 0x37, 0x02, 0x00, 0x00, + // 391 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0xcf, 0x4b, 0xeb, 0x40, + 0x10, 0x7e, 0x49, 0xfa, 0xfa, 0x5e, 0xa7, 0xb5, 0x96, 0x45, 0x6c, 0x08, 0xa8, 0x21, 0x07, 0xcd, + 0x29, 0x48, 0x7a, 0x17, 0xec, 0xc5, 0x83, 0x05, 0x65, 0x3d, 0x08, 0x7a, 0x28, 0x49, 0xb3, 0xd8, + 0x85, 0xb4, 0x1b, 0xb3, 0x6b, 0xa1, 0x9e, 0xbc, 0xfa, 0x5f, 0x4b, 0x76, 0xf3, 0xab, 0xd6, 0xa8, + 0xd0, 0xdb, 0xec, 0xec, 0xec, 0xf7, 0x7d, 0xf3, 0xcd, 0x2c, 0x40, 0x18, 0xb3, 0xd0, 0x4b, 0x52, + 0x26, 0x18, 0x6a, 0x3f, 0x51, 0x11, 0xc4, 0x6b, 0xab, 0xc7, 0xe7, 0x41, 0x4a, 0x22, 0x95, 0x75, + 0x62, 0xe8, 0x5f, 0x11, 0x31, 0x8e, 0x59, 0x88, 0xc9, 0xf3, 0x0b, 0xe1, 0x02, 0xf9, 0x00, 0x29, + 0x49, 0x18, 0xa7, 0x82, 0xa5, 0x6b, 0x53, 0xb3, 0x35, 0xb7, 0xeb, 0x23, 0x4f, 0x3d, 0xf6, 0x70, + 0x79, 0x83, 0x6b, 0x55, 0x68, 0x00, 0x06, 0xa3, 0x91, 0xa9, 0xdb, 0x9a, 0xdb, 0xc1, 0x59, 0x88, + 0x0e, 0xe0, 0x6f, 0x4c, 0x17, 0x54, 0x98, 0x86, 0xad, 0xb9, 0x06, 0x56, 0x07, 0xe7, 0x1a, 0xf6, + 0x4b, 0x36, 0x9e, 0xb0, 0x25, 0x27, 0x08, 0x41, 0x8b, 0xd3, 0x57, 0x22, 0x89, 0x0c, 0x2c, 0xe3, + 0x2c, 0x17, 0x05, 0x22, 0x90, 0x78, 0x3d, 0x2c, 0xe3, 0x82, 0xc2, 0x28, 0x29, 0x1c, 0x56, 0x82, + 0xf1, 0x5d, 0xb4, 0x23, 0x68, 0x31, 0x1a, 0x71, 0x53, 0xb7, 0x0d, 0xb7, 0x83, 0x65, 0xdc, 0xa0, + 0x7e, 0x02, 0x83, 0x8a, 0x70, 0x67, 0xf9, 0xef, 0x3a, 0x1c, 0x4f, 0x28, 0x57, 0x78, 0xe3, 0x35, + 0x26, 0x2b, 0xca, 0x29, 0x5b, 0xde, 0x06, 0x62, 0xbe, 0x4b, 0x3b, 0x0f, 0xd0, 0x4f, 0x73, 0xa8, + 0x69, 0x12, 0x88, 0xb9, 0x6a, 0xac, 0xeb, 0x8f, 0x8a, 0x77, 0xdf, 0x73, 0x7a, 0x1b, 0xb9, 0xbd, + 0xb4, 0x76, 0xe2, 0xd6, 0x3d, 0xf4, 0xea, 0xd7, 0xe8, 0x08, 0x60, 0xc6, 0x16, 0x0b, 0x2a, 0xa6, + 0x59, 0x6f, 0x9a, 0xec, 0xad, 0xa3, 0x32, 0x37, 0x34, 0xca, 0x7c, 0xc8, 0x14, 0xe4, 0x6b, 0x21, + 0xe3, 0x06, 0x67, 0x1f, 0xe1, 0xa4, 0x51, 0x56, 0x6e, 0x74, 0x6e, 0xa0, 0x56, 0xad, 0xd8, 0x57, + 0x36, 0x17, 0xe3, 0x30, 0xaa, 0x71, 0xf8, 0x6f, 0x3a, 0x74, 0x33, 0xe4, 0x3b, 0x92, 0xae, 0xe8, + 0x8c, 0xa0, 0x0b, 0xf8, 0x97, 0x8f, 0x11, 0x1d, 0x16, 0xa6, 0x6c, 0xfe, 0x01, 0x6b, 0xb8, 0x95, + 0x57, 0x2a, 0x9c, 0x3f, 0xe7, 0x1a, 0xba, 0x84, 0xff, 0xc5, 0x1a, 0xa0, 0xcf, 0x85, 0xc5, 0x26, + 0x5a, 0xe6, 0xf6, 0x45, 0x0d, 0x62, 0x09, 0xc3, 0x86, 0x7e, 0xd1, 0xe9, 0xef, 0xe6, 0x64, 0x9d, + 0xfd, 0x58, 0x57, 0xf1, 0x85, 0x6d, 0xf9, 0xd9, 0x47, 0x1f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe8, + 0xae, 0xac, 0xa9, 0x10, 0x04, 0x00, 0x00, } diff --git a/vendor/vendor.json b/vendor/vendor.json index daf5d0855..871b26d1e 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -201,12 +201,10 @@ "revisionTime": "2017-01-30T11:31:45Z" }, { - "checksumSHA1": "jTJBhnPKmona+1U7mbfFjodrGUQ=", + "checksumSHA1": "8aU1nl/TLdoNHESvyTh6pxVJ4Ys=", "path": "gitlab.com/gitlab-org/gitaly-proto/go", - "revision": "a74d4f2565d3461fa699f1d58df099a06f3a631c", - "revisionTime": "2017-12-08T15:42:58Z", - "version": "v0.61.0", - "versionExact": "v0.61.0" + "revision": "00d5cc5285e690a847c310c5589027671752dea3", + "revisionTime": "2017-12-14T08:42:55Z" }, { "checksumSHA1": "nqWNlnMmVpt628zzvyo6Yv2CX5Q=", -- cgit v1.2.3