From a73c61703276f8afea28c76eda913fd65a608f6c Mon Sep 17 00:00:00 2001 From: Siddharth Asthana Date: Tue, 13 Jun 2023 16:25:15 +0530 Subject: [PATCH 1/2] proto: add range-diff related messages and service Signed-off-by: Siddharth Asthana --- proto/go/gitalypb/protolist.go | 1 + proto/go/gitalypb/rangediff.pb.go | 592 +++++++++++++++++++++++++ proto/go/gitalypb/rangediff_grpc.pb.go | 197 ++++++++ proto/rangediff.proto | 96 ++++ 4 files changed, 886 insertions(+) create mode 100644 proto/go/gitalypb/rangediff.pb.go create mode 100644 proto/go/gitalypb/rangediff_grpc.pb.go create mode 100644 proto/rangediff.proto diff --git a/proto/go/gitalypb/protolist.go b/proto/go/gitalypb/protolist.go index 7a7aac0eba..27962fb35c 100644 --- a/proto/go/gitalypb/protolist.go +++ b/proto/go/gitalypb/protolist.go @@ -19,6 +19,7 @@ var GitalyProtos = []string{ "operations.proto", "packfile.proto", "praefect.proto", + "rangediff.proto", "ref.proto", "remote.proto", "repository.proto", diff --git a/proto/go/gitalypb/rangediff.pb.go b/proto/go/gitalypb/rangediff.pb.go new file mode 100644 index 0000000000..2f0fe21e43 --- /dev/null +++ b/proto/go/gitalypb/rangediff.pb.go @@ -0,0 +1,592 @@ +// This file implements RPC service for git-range-diff comparison. +// For a detailed explanation and documentation of git range-diff, +// please refer to: https://git-scm.com/docs/git-range-diff + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v4.23.1 +// source: rangediff.proto + +package gitalypb + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Enum to specify the type of commit range notation. +type RangeDiffRequest_RangeNotation int32 + +const ( + // Specifies the notation. + RangeDiffRequest_TWO_RANGES RangeDiffRequest_RangeNotation = 0 + // Specifies the ... notation. + RangeDiffRequest_TWO_REVS RangeDiffRequest_RangeNotation = 1 + // Specifies the notation. + RangeDiffRequest_BASE_AND_REVS RangeDiffRequest_RangeNotation = 2 +) + +// Enum value maps for RangeDiffRequest_RangeNotation. +var ( + RangeDiffRequest_RangeNotation_name = map[int32]string{ + 0: "TWO_RANGES", + 1: "TWO_REVS", + 2: "BASE_AND_REVS", + } + RangeDiffRequest_RangeNotation_value = map[string]int32{ + "TWO_RANGES": 0, + "TWO_REVS": 1, + "BASE_AND_REVS": 2, + } +) + +func (x RangeDiffRequest_RangeNotation) Enum() *RangeDiffRequest_RangeNotation { + p := new(RangeDiffRequest_RangeNotation) + *p = x + return p +} + +func (x RangeDiffRequest_RangeNotation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RangeDiffRequest_RangeNotation) Descriptor() protoreflect.EnumDescriptor { + return file_rangediff_proto_enumTypes[0].Descriptor() +} + +func (RangeDiffRequest_RangeNotation) Type() protoreflect.EnumType { + return &file_rangediff_proto_enumTypes[0] +} + +func (x RangeDiffRequest_RangeNotation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RangeDiffRequest_RangeNotation.Descriptor instead. +func (RangeDiffRequest_RangeNotation) EnumDescriptor() ([]byte, []int) { + return file_rangediff_proto_rawDescGZIP(), []int{0, 0} +} + +// Enum to specify the format of the response. +type RangeDiffRequest_ResponseFormat int32 + +const ( + // For unparsed output + RangeDiffRequest_UNPARSED_OUTPUT RangeDiffRequest_ResponseFormat = 0 + // Parsed output + RangeDiffRequest_PARSED_OUTPUT RangeDiffRequest_ResponseFormat = 1 + // Both + RangeDiffRequest_BOTH RangeDiffRequest_ResponseFormat = 2 +) + +// Enum value maps for RangeDiffRequest_ResponseFormat. +var ( + RangeDiffRequest_ResponseFormat_name = map[int32]string{ + 0: "UNPARSED_OUTPUT", + 1: "PARSED_OUTPUT", + 2: "BOTH", + } + RangeDiffRequest_ResponseFormat_value = map[string]int32{ + "UNPARSED_OUTPUT": 0, + "PARSED_OUTPUT": 1, + "BOTH": 2, + } +) + +func (x RangeDiffRequest_ResponseFormat) Enum() *RangeDiffRequest_ResponseFormat { + p := new(RangeDiffRequest_ResponseFormat) + *p = x + return p +} + +func (x RangeDiffRequest_ResponseFormat) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RangeDiffRequest_ResponseFormat) Descriptor() protoreflect.EnumDescriptor { + return file_rangediff_proto_enumTypes[1].Descriptor() +} + +func (RangeDiffRequest_ResponseFormat) Type() protoreflect.EnumType { + return &file_rangediff_proto_enumTypes[1] +} + +func (x RangeDiffRequest_ResponseFormat) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RangeDiffRequest_ResponseFormat.Descriptor instead. +func (RangeDiffRequest_ResponseFormat) EnumDescriptor() ([]byte, []int) { + return file_rangediff_proto_rawDescGZIP(), []int{0, 1} +} + +// The comparison relationship between the two commits. +type RangeDiffResponse_Comparison int32 + +const ( + // Indicates that the commit remains unmodified between the two ranges (=). + RangeDiffResponse_UNMODIFIED RangeDiffResponse_Comparison = 0 + // Indicates that the commit has been modified between the two ranges (!). + RangeDiffResponse_MODIFIED RangeDiffResponse_Comparison = 1 + // Indicates that the commit was removed in the second range (<). + RangeDiffResponse_REMOVED RangeDiffResponse_Comparison = 2 + // Indicates that the commit was added in the second range (>). + RangeDiffResponse_ADDED RangeDiffResponse_Comparison = 3 +) + +// Enum value maps for RangeDiffResponse_Comparison. +var ( + RangeDiffResponse_Comparison_name = map[int32]string{ + 0: "UNMODIFIED", + 1: "MODIFIED", + 2: "REMOVED", + 3: "ADDED", + } + RangeDiffResponse_Comparison_value = map[string]int32{ + "UNMODIFIED": 0, + "MODIFIED": 1, + "REMOVED": 2, + "ADDED": 3, + } +) + +func (x RangeDiffResponse_Comparison) Enum() *RangeDiffResponse_Comparison { + p := new(RangeDiffResponse_Comparison) + *p = x + return p +} + +func (x RangeDiffResponse_Comparison) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RangeDiffResponse_Comparison) Descriptor() protoreflect.EnumDescriptor { + return file_rangediff_proto_enumTypes[2].Descriptor() +} + +func (RangeDiffResponse_Comparison) Type() protoreflect.EnumType { + return &file_rangediff_proto_enumTypes[2] +} + +func (x RangeDiffResponse_Comparison) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RangeDiffResponse_Comparison.Descriptor instead. +func (RangeDiffResponse_Comparison) EnumDescriptor() ([]byte, []int) { + return file_rangediff_proto_rawDescGZIP(), []int{1, 0} +} + +// Request for range difference comparison +type RangeDiffRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // This comment is left unintentionally blank. + Repository *Repository `protobuf:"bytes,1,opt,name=repository,proto3" json:"repository,omitempty"` + // The commit range notation to use. + RangeNotation RangeDiffRequest_RangeNotation `protobuf:"varint,2,opt,name=range_notation,json=rangeNotation,proto3,enum=gitaly.RangeDiffRequest_RangeNotation" json:"range_notation,omitempty"` + // The base revision. Corresponds to the '' argument of git range-diff, + // so only used with the BASE_AND_REVS notation. + BaseRev string `protobuf:"bytes,3,opt,name=base_rev,json=baseRev,proto3" json:"base_rev,omitempty"` + // The first commit range or revision. Corresponds to the '' argument of git range-diff with + // the TWO_RANGES notation, and to the '' argument with the TWO_REVS and BASE_AND_REVS notations. + Rev1OrRange1 string `protobuf:"bytes,4,opt,name=rev1_or_range1,json=rev1OrRange1,proto3" json:"rev1_or_range1,omitempty"` + // The second commit range or revision. Corresponds to the '' argument of git range-diff with + // the TWO_RANGES notation, and to the '' argument with the TWO_REVS and BASE_AND_REVS notations. + Rev2OrRange2 string `protobuf:"bytes,5,opt,name=rev2_or_range2,json=rev2OrRange2,proto3" json:"rev2_or_range2,omitempty"` + // The response format. + ResponseFormat RangeDiffRequest_ResponseFormat `protobuf:"varint,6,opt,name=response_format,json=responseFormat,proto3,enum=gitaly.RangeDiffRequest_ResponseFormat" json:"response_format,omitempty"` +} + +func (x *RangeDiffRequest) Reset() { + *x = RangeDiffRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_rangediff_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RangeDiffRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RangeDiffRequest) ProtoMessage() {} + +func (x *RangeDiffRequest) ProtoReflect() protoreflect.Message { + mi := &file_rangediff_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RangeDiffRequest.ProtoReflect.Descriptor instead. +func (*RangeDiffRequest) Descriptor() ([]byte, []int) { + return file_rangediff_proto_rawDescGZIP(), []int{0} +} + +func (x *RangeDiffRequest) GetRepository() *Repository { + if x != nil { + return x.Repository + } + return nil +} + +func (x *RangeDiffRequest) GetRangeNotation() RangeDiffRequest_RangeNotation { + if x != nil { + return x.RangeNotation + } + return RangeDiffRequest_TWO_RANGES +} + +func (x *RangeDiffRequest) GetBaseRev() string { + if x != nil { + return x.BaseRev + } + return "" +} + +func (x *RangeDiffRequest) GetRev1OrRange1() string { + if x != nil { + return x.Rev1OrRange1 + } + return "" +} + +func (x *RangeDiffRequest) GetRev2OrRange2() string { + if x != nil { + return x.Rev2OrRange2 + } + return "" +} + +func (x *RangeDiffRequest) GetResponseFormat() RangeDiffRequest_ResponseFormat { + if x != nil { + return x.ResponseFormat + } + return RangeDiffRequest_UNPARSED_OUTPUT +} + +// Response for range difference comparison +type RangeDiffResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The commit in the first range. + Commit1 *GitCommit `protobuf:"bytes,1,opt,name=commit1,proto3" json:"commit1,omitempty"` + // The commit in the second range. + Commit2 *GitCommit `protobuf:"bytes,2,opt,name=commit2,proto3" json:"commit2,omitempty"` + // Diff lines between the two commits. + DiffLines []byte `protobuf:"bytes,4,opt,name=diff_lines,json=diffLines,proto3" json:"diff_lines,omitempty"` + // The comparison result between the two commits. + Comparison RangeDiffResponse_Comparison `protobuf:"varint,6,opt,name=comparison,proto3,enum=gitaly.RangeDiffResponse_Comparison" json:"comparison,omitempty"` +} + +func (x *RangeDiffResponse) Reset() { + *x = RangeDiffResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rangediff_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RangeDiffResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RangeDiffResponse) ProtoMessage() {} + +func (x *RangeDiffResponse) ProtoReflect() protoreflect.Message { + mi := &file_rangediff_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RangeDiffResponse.ProtoReflect.Descriptor instead. +func (*RangeDiffResponse) Descriptor() ([]byte, []int) { + return file_rangediff_proto_rawDescGZIP(), []int{1} +} + +func (x *RangeDiffResponse) GetCommit1() *GitCommit { + if x != nil { + return x.Commit1 + } + return nil +} + +func (x *RangeDiffResponse) GetCommit2() *GitCommit { + if x != nil { + return x.Commit2 + } + return nil +} + +func (x *RangeDiffResponse) GetDiffLines() []byte { + if x != nil { + return x.DiffLines + } + return nil +} + +func (x *RangeDiffResponse) GetComparison() RangeDiffResponse_Comparison { + if x != nil { + return x.Comparison + } + return RangeDiffResponse_UNMODIFIED +} + +// The raw range difference data. +type RawRangeDiffResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The raw range difference data. + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *RawRangeDiffResponse) Reset() { + *x = RawRangeDiffResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_rangediff_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RawRangeDiffResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RawRangeDiffResponse) ProtoMessage() {} + +func (x *RawRangeDiffResponse) ProtoReflect() protoreflect.Message { + mi := &file_rangediff_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RawRangeDiffResponse.ProtoReflect.Descriptor instead. +func (*RawRangeDiffResponse) Descriptor() ([]byte, []int) { + return file_rangediff_proto_rawDescGZIP(), []int{2} +} + +func (x *RawRangeDiffResponse) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +var File_rangediff_proto protoreflect.FileDescriptor + +var file_rangediff_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x69, 0x66, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x06, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x1a, 0x0a, 0x6c, 0x69, 0x6e, 0x74, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0c, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0xda, 0x03, 0x0a, 0x10, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, + 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, + 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x12, 0x4d, 0x0a, 0x0e, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x76, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x76, 0x12, 0x24, 0x0a, 0x0e, + 0x72, 0x65, 0x76, 0x31, 0x5f, 0x6f, 0x72, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x31, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x31, 0x4f, 0x72, 0x52, 0x61, 0x6e, 0x67, + 0x65, 0x31, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x76, 0x32, 0x5f, 0x6f, 0x72, 0x5f, 0x72, 0x61, + 0x6e, 0x67, 0x65, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x32, + 0x4f, 0x72, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x32, 0x12, 0x50, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, + 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x40, 0x0a, 0x0d, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x4e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x0a, 0x54, + 0x57, 0x4f, 0x5f, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x53, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x54, + 0x57, 0x4f, 0x5f, 0x52, 0x45, 0x56, 0x53, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x42, 0x41, 0x53, + 0x45, 0x5f, 0x41, 0x4e, 0x44, 0x5f, 0x52, 0x45, 0x56, 0x53, 0x10, 0x02, 0x22, 0x42, 0x0a, 0x0e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x13, + 0x0a, 0x0f, 0x55, 0x4e, 0x50, 0x41, 0x52, 0x53, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, + 0x54, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x41, 0x52, 0x53, 0x45, 0x44, 0x5f, 0x4f, 0x55, + 0x54, 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x02, + 0x22, 0x96, 0x02, 0x0a, 0x11, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x2e, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x31, 0x12, 0x2b, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x32, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x69, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x32, + 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x69, 0x66, 0x66, 0x4c, 0x69, 0x6e, 0x65, 0x73, 0x12, + 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x61, 0x6e, + 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, + 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x22, 0x42, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, + 0x73, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4d, 0x4f, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x12, 0x09, + 0x0a, 0x05, 0x41, 0x44, 0x44, 0x45, 0x44, 0x10, 0x03, 0x22, 0x2a, 0x0a, 0x14, 0x52, 0x61, 0x77, + 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xb4, 0x01, 0x0a, 0x10, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, + 0x69, 0x66, 0x66, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x43, 0x6f, + 0x6d, 0x70, 0x61, 0x72, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x69, + 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, + 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x12, 0x50, 0x0a, 0x0c, 0x52, 0x61, + 0x77, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x12, 0x18, 0x2e, 0x67, 0x69, 0x74, + 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x61, + 0x77, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x30, 0x01, 0x42, 0x34, 0x5a, 0x32, + 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, + 0x62, 0x2d, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x36, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_rangediff_proto_rawDescOnce sync.Once + file_rangediff_proto_rawDescData = file_rangediff_proto_rawDesc +) + +func file_rangediff_proto_rawDescGZIP() []byte { + file_rangediff_proto_rawDescOnce.Do(func() { + file_rangediff_proto_rawDescData = protoimpl.X.CompressGZIP(file_rangediff_proto_rawDescData) + }) + return file_rangediff_proto_rawDescData +} + +var file_rangediff_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_rangediff_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_rangediff_proto_goTypes = []interface{}{ + (RangeDiffRequest_RangeNotation)(0), // 0: gitaly.RangeDiffRequest.RangeNotation + (RangeDiffRequest_ResponseFormat)(0), // 1: gitaly.RangeDiffRequest.ResponseFormat + (RangeDiffResponse_Comparison)(0), // 2: gitaly.RangeDiffResponse.Comparison + (*RangeDiffRequest)(nil), // 3: gitaly.RangeDiffRequest + (*RangeDiffResponse)(nil), // 4: gitaly.RangeDiffResponse + (*RawRangeDiffResponse)(nil), // 5: gitaly.RawRangeDiffResponse + (*Repository)(nil), // 6: gitaly.Repository + (*GitCommit)(nil), // 7: gitaly.GitCommit +} +var file_rangediff_proto_depIdxs = []int32{ + 6, // 0: gitaly.RangeDiffRequest.repository:type_name -> gitaly.Repository + 0, // 1: gitaly.RangeDiffRequest.range_notation:type_name -> gitaly.RangeDiffRequest.RangeNotation + 1, // 2: gitaly.RangeDiffRequest.response_format:type_name -> gitaly.RangeDiffRequest.ResponseFormat + 7, // 3: gitaly.RangeDiffResponse.commit1:type_name -> gitaly.GitCommit + 7, // 4: gitaly.RangeDiffResponse.commit2:type_name -> gitaly.GitCommit + 2, // 5: gitaly.RangeDiffResponse.comparison:type_name -> gitaly.RangeDiffResponse.Comparison + 3, // 6: gitaly.RangeDiffService.CompareRanges:input_type -> gitaly.RangeDiffRequest + 3, // 7: gitaly.RangeDiffService.RawRangeDiff:input_type -> gitaly.RangeDiffRequest + 4, // 8: gitaly.RangeDiffService.CompareRanges:output_type -> gitaly.RangeDiffResponse + 5, // 9: gitaly.RangeDiffService.RawRangeDiff:output_type -> gitaly.RawRangeDiffResponse + 8, // [8:10] is the sub-list for method output_type + 6, // [6:8] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_rangediff_proto_init() } +func file_rangediff_proto_init() { + if File_rangediff_proto != nil { + return + } + file_lint_proto_init() + file_shared_proto_init() + if !protoimpl.UnsafeEnabled { + file_rangediff_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RangeDiffRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rangediff_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RangeDiffResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rangediff_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RawRangeDiffResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_rangediff_proto_rawDesc, + NumEnums: 3, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_rangediff_proto_goTypes, + DependencyIndexes: file_rangediff_proto_depIdxs, + EnumInfos: file_rangediff_proto_enumTypes, + MessageInfos: file_rangediff_proto_msgTypes, + }.Build() + File_rangediff_proto = out.File + file_rangediff_proto_rawDesc = nil + file_rangediff_proto_goTypes = nil + file_rangediff_proto_depIdxs = nil +} diff --git a/proto/go/gitalypb/rangediff_grpc.pb.go b/proto/go/gitalypb/rangediff_grpc.pb.go new file mode 100644 index 0000000000..76fd5b4d4e --- /dev/null +++ b/proto/go/gitalypb/rangediff_grpc.pb.go @@ -0,0 +1,197 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v4.23.1 +// source: rangediff.proto + +package gitalypb + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// RangeDiffServiceClient is the client API for RangeDiffService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type RangeDiffServiceClient interface { + // RPC method to compare ranges and retrieve the difference + CompareRanges(ctx context.Context, in *RangeDiffRequest, opts ...grpc.CallOption) (RangeDiffService_CompareRangesClient, error) + RawRangeDiff(ctx context.Context, in *RangeDiffRequest, opts ...grpc.CallOption) (RangeDiffService_RawRangeDiffClient, error) +} + +type rangeDiffServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewRangeDiffServiceClient(cc grpc.ClientConnInterface) RangeDiffServiceClient { + return &rangeDiffServiceClient{cc} +} + +func (c *rangeDiffServiceClient) CompareRanges(ctx context.Context, in *RangeDiffRequest, opts ...grpc.CallOption) (RangeDiffService_CompareRangesClient, error) { + stream, err := c.cc.NewStream(ctx, &RangeDiffService_ServiceDesc.Streams[0], "/gitaly.RangeDiffService/CompareRanges", opts...) + if err != nil { + return nil, err + } + x := &rangeDiffServiceCompareRangesClient{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 RangeDiffService_CompareRangesClient interface { + Recv() (*RangeDiffResponse, error) + grpc.ClientStream +} + +type rangeDiffServiceCompareRangesClient struct { + grpc.ClientStream +} + +func (x *rangeDiffServiceCompareRangesClient) Recv() (*RangeDiffResponse, error) { + m := new(RangeDiffResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *rangeDiffServiceClient) RawRangeDiff(ctx context.Context, in *RangeDiffRequest, opts ...grpc.CallOption) (RangeDiffService_RawRangeDiffClient, error) { + stream, err := c.cc.NewStream(ctx, &RangeDiffService_ServiceDesc.Streams[1], "/gitaly.RangeDiffService/RawRangeDiff", opts...) + if err != nil { + return nil, err + } + x := &rangeDiffServiceRawRangeDiffClient{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 RangeDiffService_RawRangeDiffClient interface { + Recv() (*RawRangeDiffResponse, error) + grpc.ClientStream +} + +type rangeDiffServiceRawRangeDiffClient struct { + grpc.ClientStream +} + +func (x *rangeDiffServiceRawRangeDiffClient) Recv() (*RawRangeDiffResponse, error) { + m := new(RawRangeDiffResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// RangeDiffServiceServer is the server API for RangeDiffService service. +// All implementations must embed UnimplementedRangeDiffServiceServer +// for forward compatibility +type RangeDiffServiceServer interface { + // RPC method to compare ranges and retrieve the difference + CompareRanges(*RangeDiffRequest, RangeDiffService_CompareRangesServer) error + RawRangeDiff(*RangeDiffRequest, RangeDiffService_RawRangeDiffServer) error + mustEmbedUnimplementedRangeDiffServiceServer() +} + +// UnimplementedRangeDiffServiceServer must be embedded to have forward compatible implementations. +type UnimplementedRangeDiffServiceServer struct { +} + +func (UnimplementedRangeDiffServiceServer) CompareRanges(*RangeDiffRequest, RangeDiffService_CompareRangesServer) error { + return status.Errorf(codes.Unimplemented, "method CompareRanges not implemented") +} +func (UnimplementedRangeDiffServiceServer) RawRangeDiff(*RangeDiffRequest, RangeDiffService_RawRangeDiffServer) error { + return status.Errorf(codes.Unimplemented, "method RawRangeDiff not implemented") +} +func (UnimplementedRangeDiffServiceServer) mustEmbedUnimplementedRangeDiffServiceServer() {} + +// UnsafeRangeDiffServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RangeDiffServiceServer will +// result in compilation errors. +type UnsafeRangeDiffServiceServer interface { + mustEmbedUnimplementedRangeDiffServiceServer() +} + +func RegisterRangeDiffServiceServer(s grpc.ServiceRegistrar, srv RangeDiffServiceServer) { + s.RegisterService(&RangeDiffService_ServiceDesc, srv) +} + +func _RangeDiffService_CompareRanges_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(RangeDiffRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RangeDiffServiceServer).CompareRanges(m, &rangeDiffServiceCompareRangesServer{stream}) +} + +type RangeDiffService_CompareRangesServer interface { + Send(*RangeDiffResponse) error + grpc.ServerStream +} + +type rangeDiffServiceCompareRangesServer struct { + grpc.ServerStream +} + +func (x *rangeDiffServiceCompareRangesServer) Send(m *RangeDiffResponse) error { + return x.ServerStream.SendMsg(m) +} + +func _RangeDiffService_RawRangeDiff_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(RangeDiffRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(RangeDiffServiceServer).RawRangeDiff(m, &rangeDiffServiceRawRangeDiffServer{stream}) +} + +type RangeDiffService_RawRangeDiffServer interface { + Send(*RawRangeDiffResponse) error + grpc.ServerStream +} + +type rangeDiffServiceRawRangeDiffServer struct { + grpc.ServerStream +} + +func (x *rangeDiffServiceRawRangeDiffServer) Send(m *RawRangeDiffResponse) error { + return x.ServerStream.SendMsg(m) +} + +// RangeDiffService_ServiceDesc is the grpc.ServiceDesc for RangeDiffService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var RangeDiffService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "gitaly.RangeDiffService", + HandlerType: (*RangeDiffServiceServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "CompareRanges", + Handler: _RangeDiffService_CompareRanges_Handler, + ServerStreams: true, + }, + { + StreamName: "RawRangeDiff", + Handler: _RangeDiffService_RawRangeDiff_Handler, + ServerStreams: true, + }, + }, + Metadata: "rangediff.proto", +} diff --git a/proto/rangediff.proto b/proto/rangediff.proto new file mode 100644 index 0000000000..af96558b99 --- /dev/null +++ b/proto/rangediff.proto @@ -0,0 +1,96 @@ +// This file implements RPC service for git-range-diff comparison. +// For a detailed explanation and documentation of git range-diff, +// please refer to: https://git-scm.com/docs/git-range-diff + +syntax = "proto3"; + +package gitaly; + +import "lint.proto"; +import "shared.proto"; + +option go_package = "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb"; + +// Service for range difference comparison +service RangeDiffService { + // RPC method to compare ranges and retrieve the difference + rpc CompareRanges(RangeDiffRequest) returns (stream RangeDiffResponse) { + option (op_type) = { + op: ACCESSOR + }; + } + + rpc RawRangeDiff(RangeDiffRequest) returns (stream RawRangeDiffResponse) { + option (op_type) = { + op: ACCESSOR + }; + } +} + +// Request for range difference comparison +message RangeDiffRequest { + // Enum to specify the type of commit range notation. + enum RangeNotation { + // Specifies the notation. + TWO_RANGES = 0; + // Specifies the ... notation. + TWO_REVS = 1; + // Specifies the notation. + BASE_AND_REVS = 2; + } + + // Enum to specify the format of the response. + enum ResponseFormat { + // For unparsed output + UNPARSED_OUTPUT = 0; + // Parsed output + PARSED_OUTPUT = 1; + // Both + BOTH = 2; + } + + // This comment is left unintentionally blank. + Repository repository = 1 [(target_repository) = true]; + // The commit range notation to use. + RangeNotation range_notation = 2; + // The base revision. Corresponds to the '' argument of git range-diff, + // so only used with the BASE_AND_REVS notation. + string base_rev = 3; + // The first commit range or revision. Corresponds to the '' argument of git range-diff with + // the TWO_RANGES notation, and to the '' argument with the TWO_REVS and BASE_AND_REVS notations. + string rev1_or_range1 = 4; + // The second commit range or revision. Corresponds to the '' argument of git range-diff with + // the TWO_RANGES notation, and to the '' argument with the TWO_REVS and BASE_AND_REVS notations. + string rev2_or_range2 = 5; + // The response format. + ResponseFormat response_format = 6; +} + +// Response for range difference comparison +message RangeDiffResponse { + // The commit in the first range. + GitCommit commit1 = 1; + // The commit in the second range. + GitCommit commit2 = 2; + // The comparison relationship between the two commits. + enum Comparison { + // Indicates that the commit remains unmodified between the two ranges (=). + UNMODIFIED = 0; + // Indicates that the commit has been modified between the two ranges (!). + MODIFIED = 1; + // Indicates that the commit was removed in the second range (<). + REMOVED = 2; + // Indicates that the commit was added in the second range (>). + ADDED = 3; + } + // Diff lines between the two commits. + bytes diff_lines = 4; + // The comparison result between the two commits. + Comparison comparison = 6; +} + +// The raw range difference data. +message RawRangeDiffResponse { + // The raw range difference data. + bytes data = 1; +} -- GitLab From c622bdf031dfb5105e5cfe36f36fc7c975a4a722 Mon Sep 17 00:00:00 2001 From: Siddharth Asthana Date: Fri, 21 Jul 2023 01:39:28 +0530 Subject: [PATCH 2/2] Rangediff: Implement RawRangeDiff Service and Range Notation Validation Implement the RawRangeDiff function in the rangediff service to process RangeDiffRequests and send the results back to the client. The revisions and range notation from the request are validated, with unsupported range notations returning appropriate errors. An error is also returned when any revision is empty. The sendRawOutput function is introduced to execute the provided git.Command and direct the output to the supplied io.Writer. Signed-off-by: Siddharth Asthana --- .../gitaly/service/rangediff/rangediff.go | 56 ++++++++ .../service/rangediff/rangediff_test.go | 134 ++++++++++++++++++ internal/gitaly/service/rangediff/server.go | 21 +++ 3 files changed, 211 insertions(+) create mode 100644 internal/gitaly/service/rangediff/rangediff.go create mode 100644 internal/gitaly/service/rangediff/rangediff_test.go create mode 100644 internal/gitaly/service/rangediff/server.go diff --git a/internal/gitaly/service/rangediff/rangediff.go b/internal/gitaly/service/rangediff/rangediff.go new file mode 100644 index 0000000000..21409dd4de --- /dev/null +++ b/internal/gitaly/service/rangediff/rangediff.go @@ -0,0 +1,56 @@ +package rangediff + +import ( + "context" + "io" + + "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" + "gitlab.com/gitlab-org/gitaly/v16/streamio" +) + +// RawRangeDiff processes the RangeDiffRequest and sends the result back to the client. +func (s *server) RawRangeDiff(in *gitalypb.RangeDiffRequest, stream gitalypb.RangeDiffService_RawRangeDiffServer) error { + if in.GetRangeNotation() != gitalypb.RangeDiffRequest_TWO_REVS { + return structerr.NewInvalidArgument("only TWO_REVS range notation is supported") + } + + if !isValidRevision(stream.Context(), in.GetRev1OrRange1()) || !isValidRevision(stream.Context(), in.GetRev2OrRange2()) { + return structerr.NewInvalidArgument("revisions are not valid") + } + + // Create the range-diff command + cmd := git.Command{ + Name: "range-diff", + Flags: []git.Option{}, + Args: []string{in.GetRev1OrRange1(), "...", in.GetRev2OrRange2()}, + } + + sw := streamio.NewWriter(func(p []byte) error { + return stream.Send(&gitalypb.RawRangeDiffResponse{Data: p}) + }) + + return sendRawOutput(stream.Context(), s.gitCmdFactory, in.Repository, sw, cmd) +} + +// sendRawOutput runs the provided git.Command and sends the output to the provided io.Writer. +func sendRawOutput(ctx context.Context, gitCmdFactory git.CommandFactory, repo *gitalypb.Repository, sender io.Writer, subCmd git.Command) error { + cmd, err := gitCmdFactory.New(ctx, repo, subCmd) + if err != nil { + return structerr.NewInternal("cmd: %w", err) + } + + if _, err := io.Copy(sender, cmd); err != nil { + return structerr.NewAborted("send: %w", err) + } + + return cmd.Wait() +} + +func isValidRevision(ctx context.Context, revision string) bool { + if len(revision) == 0 { + return false + } + return true +} diff --git a/internal/gitaly/service/rangediff/rangediff_test.go b/internal/gitaly/service/rangediff/rangediff_test.go new file mode 100644 index 0000000000..ece1a09fb1 --- /dev/null +++ b/internal/gitaly/service/rangediff/rangediff_test.go @@ -0,0 +1,134 @@ +package rangediff + +import ( + "bytes" + "context" + "io" + "testing" + + "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" + "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +func setupRangeDiffService(tb testing.TB, ctx context.Context, opt ...testserver.GitalyServerOpt) (config.Cfg, *gitalypb.Repository, string, gitalypb.RangeDiffServiceClient) { + cfg := testcfg.Build(tb) + + addr := testserver.RunGitalyServer(tb, cfg, func(srv *grpc.Server, deps *service.Dependencies) { + gitalypb.RegisterRangeDiffServiceServer(srv, NewServer( + deps.GetLocator(), + deps.GetGitCmdFactory(), + )) + }, opt...) + cfg.SocketPath = addr + + conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(tb, err) + tb.Cleanup(func() { testhelper.MustClose(tb, conn) }) + + client := gitalypb.NewRangeDiffServiceClient(conn) + + repo, repoPath := gittest.CreateRepository(tb, ctx, cfg, gittest.CreateRepositoryConfig{ + Seed: gittest.SeedGitLabTest, + }) + + return cfg, repo, repoPath, client +} + +func TestRawRangeDiff_successful(t *testing.T) { + t.Parallel() + + ctx := testhelper.Context(t) + cfg, repoProto, _, client := setupRangeDiffService(t, ctx) + repoProto, _ = gittest.CreateRepository(t, ctx, cfg) + + request := &gitalypb.RangeDiffRequest{ + Repository: repoProto, + Rev1OrRange1: "master~2", + Rev2OrRange2: "master", + RangeNotation: gitalypb.RangeDiffRequest_TWO_REVS, + } + + stream, err := client.RawRangeDiff(ctx, request) + require.NoError(t, err) + + var buffer bytes.Buffer + writer := io.Writer(&buffer) + + for { + resp, err := stream.Recv() + if err == io.EOF { + break + } + require.NoError(t, err) + _, err = writer.Write(resp.GetData()) + require.NoError(t, err) + } +} + +func TestRawRangeDiff_inputValidation(t *testing.T) { + t.Parallel() + + ctx := testhelper.Context(t) + cfg, repoProto, _, client := setupRangeDiffService(t, ctx) + repoProto, _ = gittest.CreateRepository(t, ctx, cfg) + + tests := []struct { + desc string + request *gitalypb.RangeDiffRequest + expectedErr error + }{ + { + desc: "empty rev1 or range1", + request: &gitalypb.RangeDiffRequest{ + Repository: repoProto, + Rev2OrRange2: "master", + RangeNotation: gitalypb.RangeDiffRequest_TWO_REVS, + }, + expectedErr: structerr.NewInvalidArgument("revisions cannot be empty"), + }, + { + desc: "empty rev2 or range2", + request: &gitalypb.RangeDiffRequest{ + Repository: repoProto, + Rev1OrRange1: "master~2", + RangeNotation: gitalypb.RangeDiffRequest_TWO_REVS, + }, + expectedErr: structerr.NewInvalidArgument("revisions cannot be empty"), + }, + { + desc: "unsupported range notation", + request: &gitalypb.RangeDiffRequest{ + Repository: repoProto, + Rev1OrRange1: "master~2", + Rev2OrRange2: "master", + }, + expectedErr: structerr.NewInvalidArgument("only TWO_REVS range notation is supported"), + }, + } + + for _, tc := range tests { + t.Run(tc.desc, func(t *testing.T) { + stream, err := client.RawRangeDiff(ctx, tc.request) + require.NoError(t, err) + err = drainRawRangeDiffResponse(stream) + testhelper.RequireGrpcError(t, tc.expectedErr, err) + }) + } +} + +func drainRawRangeDiffResponse(c gitalypb.RangeDiffService_RawRangeDiffClient) error { + var err error + for err == nil { + _, err = c.Recv() + } + return err +} diff --git a/internal/gitaly/service/rangediff/server.go b/internal/gitaly/service/rangediff/server.go new file mode 100644 index 0000000000..c444be16ae --- /dev/null +++ b/internal/gitaly/service/rangediff/server.go @@ -0,0 +1,21 @@ +package rangediff + +import ( + "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" +) + +type server struct { + gitalypb.UnimplementedRangeDiffServiceServer + locator storage.Locator + gitCmdFactory git.CommandFactory +} + +// NewServer creates a new instance of a grpc RangeDiffServiceServer +func NewServer(locator storage.Locator, gitCmdFactory git.CommandFactory) gitalypb.RangeDiffServiceServer { + return &server{ + locator: locator, + gitCmdFactory: gitCmdFactory, + } +} -- GitLab