diff --git a/.travis.yml b/.travis.yml index 1723120..175dedf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: go go: - - "1.12.x" + - "1.14.x" script: - GO111MODULE=on go get -t -v ./... - diff -u <(echo -n) <(gofmt -d -s .) diff --git a/diff/diff.go b/diff/diff.go index 646602a..ce3af3e 100644 --- a/diff/diff.go +++ b/diff/diff.go @@ -1,10 +1,64 @@ package diff -import "bytes" +import ( + "bytes" + "time" +) -// NOTE: types are code-generated in diff.pb.go. +// A FileDiff represents a unified diff for a single file. +// +// A file unified diff has a header that resembles the following: +// +// --- oldname 2009-10-11 15:12:20.000000000 -0700 +// +++ newname 2009-10-11 15:12:30.000000000 -0700 +type FileDiff struct { + // the original name of the file + OrigName string + // the original timestamp (nil if not present) + OrigTime *time.Time + // the new name of the file (often same as OrigName) + NewName string + // the new timestamp (nil if not present) + NewTime *time.Time + // extended header lines (e.g., git's "new mode ", "rename from ", etc.) + Extended []string + // hunks that were changed from orig to new + Hunks []*Hunk +} -//go:generate protoc -I../../../.. -I ../../../../github.com/gogo/protobuf/protobuf -I. --gogo_out=. diff.proto +// A Hunk represents a series of changes (additions or deletions) in a file's +// unified diff. +type Hunk struct { + // starting line number in original file + OrigStartLine int32 + // number of lines the hunk applies to in the original file + OrigLines int32 + // if > 0, then the original file had a 'No newline at end of file' mark at this offset + OrigNoNewlineAt int32 + // starting line number in new file + NewStartLine int32 + // number of lines the hunk applies to in the new file + NewLines int32 + // optional section heading + Section string + // 0-indexed line offset in unified file diff (including section headers); this is + // only set when Hunks are read from entire file diff (i.e., when ReadAllHunks is + // called) This accounts for hunk headers, too, so the StartPosition of the first + // hunk will be 1. + StartPosition int32 + // hunk body (lines prefixed with '-', '+', or ' ') + Body []byte +} + +// A Stat is a diff stat that represents the number of lines added/changed/deleted. +type Stat struct { + // number of lines added + Added int32 + // number of lines changed + Changed int32 + // number of lines deleted + Deleted int32 +} // Stat computes the number of lines added/changed/deleted in all // hunks in this file's diff. diff --git a/diff/diff.pb.go b/diff/diff.pb.go deleted file mode 100644 index 2e7c27f..0000000 --- a/diff/diff.pb.go +++ /dev/null @@ -1,1059 +0,0 @@ -// Code generated by protoc-gen-gogo. -// source: diff.proto -// DO NOT EDIT! - -/* - Package diff is a generated protocol buffer package. - - It is generated from these files: - diff.proto - - It has these top-level messages: - FileDiff - Hunk - Stat -*/ -package diff - -import proto "github.com/gogo/protobuf/proto" -import fmt "fmt" -import math "math" - -// discarding unused import gogoproto "github.com/gogo/protobuf/gogoproto" -import pbtypes "sourcegraph.com/sqs/pbtypes" - -import io "io" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// A FileDiff represents a unified diff for a single file. -// -// A file unified diff has a header that resembles the following: -// -// --- oldname 2009-10-11 15:12:20.000000000 -0700 -// +++ newname 2009-10-11 15:12:30.000000000 -0700 -type FileDiff struct { - // the original name of the file - OrigName string `protobuf:"bytes,1,opt,name=OrigName,proto3" json:"OrigName,omitempty"` - // the original timestamp (nil if not present) - OrigTime *pbtypes.Timestamp `protobuf:"bytes,2,opt,name=OrigTime" json:"OrigTime,omitempty"` - // the new name of the file (often same as OrigName) - NewName string `protobuf:"bytes,3,opt,name=NewName,proto3" json:"NewName,omitempty"` - // the new timestamp (nil if not present) - NewTime *pbtypes.Timestamp `protobuf:"bytes,4,opt,name=NewTime" json:"NewTime,omitempty"` - // extended header lines (e.g., git's "new mode ", "rename from ", etc.) - Extended []string `protobuf:"bytes,5,rep,name=Extended" json:"Extended,omitempty"` - // hunks that were changed from orig to new - Hunks []*Hunk `protobuf:"bytes,6,rep,name=Hunks" json:"Hunks,omitempty"` -} - -func (m *FileDiff) Reset() { *m = FileDiff{} } -func (m *FileDiff) String() string { return proto.CompactTextString(m) } -func (*FileDiff) ProtoMessage() {} - -// A Hunk represents a series of changes (additions or deletions) in a file's -// unified diff. -type Hunk struct { - // starting line number in original file - OrigStartLine int32 `protobuf:"varint,1,opt,name=OrigStartLine,proto3" json:"OrigStartLine,omitempty"` - // number of lines the hunk applies to in the original file - OrigLines int32 `protobuf:"varint,2,opt,name=OrigLines,proto3" json:"OrigLines,omitempty"` - // if > 0, then the original file had a 'No newline at end of file' mark at this offset - OrigNoNewlineAt int32 `protobuf:"varint,3,opt,name=OrigNoNewlineAt,proto3" json:"OrigNoNewlineAt,omitempty"` - // starting line number in new file - NewStartLine int32 `protobuf:"varint,4,opt,name=NewStartLine,proto3" json:"NewStartLine,omitempty"` - // number of lines the hunk applies to in the new file - NewLines int32 `protobuf:"varint,5,opt,name=NewLines,proto3" json:"NewLines,omitempty"` - // optional section heading - Section string `protobuf:"bytes,6,opt,name=Section,proto3" json:"Section,omitempty"` - // 0-indexed line offset in unified file diff (including section headers); this is - // only set when Hunks are read from entire file diff (i.e., when ReadAllHunks is - // called) This accounts for hunk headers, too, so the StartPosition of the first - // hunk will be 1. - StartPosition int32 `protobuf:"varint,7,opt,name=StartPosition,proto3" json:"StartPosition,omitempty"` - // hunk body (lines prefixed with '-', '+', or ' ') - Body []byte `protobuf:"bytes,8,opt,name=Body,proto3" json:"Body,omitempty"` -} - -func (m *Hunk) Reset() { *m = Hunk{} } -func (m *Hunk) String() string { return proto.CompactTextString(m) } -func (*Hunk) ProtoMessage() {} - -// A Stat is a diff stat that represents the number of lines added/changed/deleted. -type Stat struct { - // number of lines added - Added int32 `protobuf:"varint,1,opt,name=Added,proto3" json:""` - // number of lines changed - Changed int32 `protobuf:"varint,2,opt,name=Changed,proto3" json:""` - // number of lines deleted - Deleted int32 `protobuf:"varint,3,opt,name=Deleted,proto3" json:""` -} - -func (m *Stat) Reset() { *m = Stat{} } -func (m *Stat) String() string { return proto.CompactTextString(m) } -func (*Stat) ProtoMessage() {} - -func (m *FileDiff) Marshal() (data []byte, err error) { - size := m.Size() - data = make([]byte, size) - n, err := m.MarshalTo(data) - if err != nil { - return nil, err - } - return data[:n], nil -} - -func (m *FileDiff) MarshalTo(data []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if len(m.OrigName) > 0 { - data[i] = 0xa - i++ - i = encodeVarintDiff(data, i, uint64(len(m.OrigName))) - i += copy(data[i:], m.OrigName) - } - if m.OrigTime != nil { - data[i] = 0x12 - i++ - i = encodeVarintDiff(data, i, uint64(m.OrigTime.Size())) - n1, err := m.OrigTime.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n1 - } - if len(m.NewName) > 0 { - data[i] = 0x1a - i++ - i = encodeVarintDiff(data, i, uint64(len(m.NewName))) - i += copy(data[i:], m.NewName) - } - if m.NewTime != nil { - data[i] = 0x22 - i++ - i = encodeVarintDiff(data, i, uint64(m.NewTime.Size())) - n2, err := m.NewTime.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n2 - } - if len(m.Extended) > 0 { - for _, s := range m.Extended { - data[i] = 0x2a - i++ - l = len(s) - for l >= 1<<7 { - data[i] = uint8(uint64(l)&0x7f | 0x80) - l >>= 7 - i++ - } - data[i] = uint8(l) - i++ - i += copy(data[i:], s) - } - } - if len(m.Hunks) > 0 { - for _, msg := range m.Hunks { - data[i] = 0x32 - i++ - i = encodeVarintDiff(data, i, uint64(msg.Size())) - n, err := msg.MarshalTo(data[i:]) - if err != nil { - return 0, err - } - i += n - } - } - return i, nil -} - -func (m *Hunk) Marshal() (data []byte, err error) { - size := m.Size() - data = make([]byte, size) - n, err := m.MarshalTo(data) - if err != nil { - return nil, err - } - return data[:n], nil -} - -func (m *Hunk) MarshalTo(data []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.OrigStartLine != 0 { - data[i] = 0x8 - i++ - i = encodeVarintDiff(data, i, uint64(m.OrigStartLine)) - } - if m.OrigLines != 0 { - data[i] = 0x10 - i++ - i = encodeVarintDiff(data, i, uint64(m.OrigLines)) - } - if m.OrigNoNewlineAt != 0 { - data[i] = 0x18 - i++ - i = encodeVarintDiff(data, i, uint64(m.OrigNoNewlineAt)) - } - if m.NewStartLine != 0 { - data[i] = 0x20 - i++ - i = encodeVarintDiff(data, i, uint64(m.NewStartLine)) - } - if m.NewLines != 0 { - data[i] = 0x28 - i++ - i = encodeVarintDiff(data, i, uint64(m.NewLines)) - } - if len(m.Section) > 0 { - data[i] = 0x32 - i++ - i = encodeVarintDiff(data, i, uint64(len(m.Section))) - i += copy(data[i:], m.Section) - } - if m.StartPosition != 0 { - data[i] = 0x38 - i++ - i = encodeVarintDiff(data, i, uint64(m.StartPosition)) - } - if m.Body != nil { - if len(m.Body) > 0 { - data[i] = 0x42 - i++ - i = encodeVarintDiff(data, i, uint64(len(m.Body))) - i += copy(data[i:], m.Body) - } - } - return i, nil -} - -func (m *Stat) Marshal() (data []byte, err error) { - size := m.Size() - data = make([]byte, size) - n, err := m.MarshalTo(data) - if err != nil { - return nil, err - } - return data[:n], nil -} - -func (m *Stat) MarshalTo(data []byte) (int, error) { - var i int - _ = i - var l int - _ = l - if m.Added != 0 { - data[i] = 0x8 - i++ - i = encodeVarintDiff(data, i, uint64(m.Added)) - } - if m.Changed != 0 { - data[i] = 0x10 - i++ - i = encodeVarintDiff(data, i, uint64(m.Changed)) - } - if m.Deleted != 0 { - data[i] = 0x18 - i++ - i = encodeVarintDiff(data, i, uint64(m.Deleted)) - } - return i, nil -} - -func encodeFixed64Diff(data []byte, offset int, v uint64) int { - data[offset] = uint8(v) - data[offset+1] = uint8(v >> 8) - data[offset+2] = uint8(v >> 16) - data[offset+3] = uint8(v >> 24) - data[offset+4] = uint8(v >> 32) - data[offset+5] = uint8(v >> 40) - data[offset+6] = uint8(v >> 48) - data[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Diff(data []byte, offset int, v uint32) int { - data[offset] = uint8(v) - data[offset+1] = uint8(v >> 8) - data[offset+2] = uint8(v >> 16) - data[offset+3] = uint8(v >> 24) - return offset + 4 -} -func encodeVarintDiff(data []byte, offset int, v uint64) int { - for v >= 1<<7 { - data[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - data[offset] = uint8(v) - return offset + 1 -} -func (m *FileDiff) Size() (n int) { - var l int - _ = l - l = len(m.OrigName) - if l > 0 { - n += 1 + l + sovDiff(uint64(l)) - } - if m.OrigTime != nil { - l = m.OrigTime.Size() - n += 1 + l + sovDiff(uint64(l)) - } - l = len(m.NewName) - if l > 0 { - n += 1 + l + sovDiff(uint64(l)) - } - if m.NewTime != nil { - l = m.NewTime.Size() - n += 1 + l + sovDiff(uint64(l)) - } - if len(m.Extended) > 0 { - for _, s := range m.Extended { - l = len(s) - n += 1 + l + sovDiff(uint64(l)) - } - } - if len(m.Hunks) > 0 { - for _, e := range m.Hunks { - l = e.Size() - n += 1 + l + sovDiff(uint64(l)) - } - } - return n -} - -func (m *Hunk) Size() (n int) { - var l int - _ = l - if m.OrigStartLine != 0 { - n += 1 + sovDiff(uint64(m.OrigStartLine)) - } - if m.OrigLines != 0 { - n += 1 + sovDiff(uint64(m.OrigLines)) - } - if m.OrigNoNewlineAt != 0 { - n += 1 + sovDiff(uint64(m.OrigNoNewlineAt)) - } - if m.NewStartLine != 0 { - n += 1 + sovDiff(uint64(m.NewStartLine)) - } - if m.NewLines != 0 { - n += 1 + sovDiff(uint64(m.NewLines)) - } - l = len(m.Section) - if l > 0 { - n += 1 + l + sovDiff(uint64(l)) - } - if m.StartPosition != 0 { - n += 1 + sovDiff(uint64(m.StartPosition)) - } - if m.Body != nil { - l = len(m.Body) - if l > 0 { - n += 1 + l + sovDiff(uint64(l)) - } - } - return n -} - -func (m *Stat) Size() (n int) { - var l int - _ = l - if m.Added != 0 { - n += 1 + sovDiff(uint64(m.Added)) - } - if m.Changed != 0 { - n += 1 + sovDiff(uint64(m.Changed)) - } - if m.Deleted != 0 { - n += 1 + sovDiff(uint64(m.Deleted)) - } - return n -} - -func sovDiff(x uint64) (n int) { - for { - n++ - x >>= 7 - if x == 0 { - break - } - } - return n -} -func sozDiff(x uint64) (n int) { - return sovDiff(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *FileDiff) Unmarshal(data []byte) error { - l := len(data) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: FileDiff: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: FileDiff: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OrigName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.OrigName = string(data[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field OrigTime", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.OrigTime == nil { - m.OrigTime = &pbtypes.Timestamp{} - } - if err := m.OrigTime.Unmarshal(data[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NewName", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.NewName = string(data[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NewTime", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.NewTime == nil { - m.NewTime = &pbtypes.Timestamp{} - } - if err := m.NewTime.Unmarshal(data[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Extended", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Extended = append(m.Extended, string(data[iNdEx:postIndex])) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Hunks", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - msglen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + msglen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Hunks = append(m.Hunks, &Hunk{}) - if err := m.Hunks[len(m.Hunks)-1].Unmarshal(data[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipDiff(data[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthDiff - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Hunk) Unmarshal(data []byte) error { - l := len(data) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Hunk: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Hunk: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OrigStartLine", wireType) - } - m.OrigStartLine = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.OrigStartLine |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OrigLines", wireType) - } - m.OrigLines = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.OrigLines |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field OrigNoNewlineAt", wireType) - } - m.OrigNoNewlineAt = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.OrigNoNewlineAt |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NewStartLine", wireType) - } - m.NewStartLine = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.NewStartLine |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NewLines", wireType) - } - m.NewLines = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.NewLines |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Section", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - stringLen |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + intStringLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Section = string(data[iNdEx:postIndex]) - iNdEx = postIndex - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field StartPosition", wireType) - } - m.StartPosition = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.StartPosition |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Body", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - byteLen |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthDiff - } - postIndex := iNdEx + byteLen - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Body = append([]byte{}, data[iNdEx:postIndex]...) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipDiff(data[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthDiff - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Stat) Unmarshal(data []byte) error { - l := len(data) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Stat: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Stat: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Added", wireType) - } - m.Added = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.Added |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Changed", wireType) - } - m.Changed = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.Changed |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Deleted", wireType) - } - m.Deleted = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowDiff - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - m.Deleted |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipDiff(data[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthDiff - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipDiff(data []byte) (n int, err error) { - l := len(data) - iNdEx := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDiff - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDiff - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if data[iNdEx-1] < 0x80 { - break - } - } - return iNdEx, nil - case 1: - iNdEx += 8 - return iNdEx, nil - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDiff - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - iNdEx += length - if length < 0 { - return 0, ErrInvalidLengthDiff - } - return iNdEx, nil - case 3: - for { - var innerWire uint64 - var start int = iNdEx - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowDiff - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := data[iNdEx] - iNdEx++ - innerWire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - innerWireType := int(innerWire & 0x7) - if innerWireType == 4 { - break - } - next, err := skipDiff(data[start:]) - if err != nil { - return 0, err - } - iNdEx = start + next - } - return iNdEx, nil - case 4: - return iNdEx, nil - case 5: - iNdEx += 4 - return iNdEx, nil - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - } - panic("unreachable") -} - -var ( - ErrInvalidLengthDiff = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowDiff = fmt.Errorf("proto: integer overflow") -) diff --git a/diff/diff.proto b/diff/diff.proto deleted file mode 100644 index 8868970..0000000 --- a/diff/diff.proto +++ /dev/null @@ -1,81 +0,0 @@ -syntax = "proto3"; -package diff; - -import "github.com/gogo/protobuf/gogoproto/gogo.proto"; -import "sourcegraph.com/sqs/pbtypes/timestamp.proto"; - -option (gogoproto.goproto_getters_all) = false; -option (gogoproto.unmarshaler_all) = true; -option (gogoproto.marshaler_all) = true; -option (gogoproto.sizer_all) = true; - -// A FileDiff represents a unified diff for a single file. -// -// A file unified diff has a header that resembles the following: -// -// --- oldname 2009-10-11 15:12:20.000000000 -0700 -// +++ newname 2009-10-11 15:12:30.000000000 -0700 -message FileDiff { - // the original name of the file - string OrigName = 1; - - // the original timestamp (nil if not present) - pbtypes.Timestamp OrigTime = 2; - - // the new name of the file (often same as OrigName) - string NewName = 3; - - // the new timestamp (nil if not present) - pbtypes.Timestamp NewTime = 4; - - // extended header lines (e.g., git's "new mode ", "rename from ", etc.) - repeated string Extended = 5; - - // hunks that were changed from orig to new - repeated Hunk Hunks = 6; -} - - -// A Hunk represents a series of changes (additions or deletions) in a file's -// unified diff. -message Hunk { - // starting line number in original file - int32 OrigStartLine = 1; - - // number of lines the hunk applies to in the original file - int32 OrigLines = 2; - - // if > 0, then the original file had a 'No newline at end of file' mark at this offset - int32 OrigNoNewlineAt = 3; - - // starting line number in new file - int32 NewStartLine = 4; - - // number of lines the hunk applies to in the new file - int32 NewLines = 5; - - // optional section heading - string Section = 6; - - // 0-indexed line offset in unified file diff (including section headers); this is - // only set when Hunks are read from entire file diff (i.e., when ReadAllHunks is - // called) This accounts for hunk headers, too, so the StartPosition of the first - // hunk will be 1. - int32 StartPosition = 7; - - // hunk body (lines prefixed with '-', '+', or ' ') - bytes Body = 8; -} - -// A Stat is a diff stat that represents the number of lines added/changed/deleted. -message Stat { - // number of lines added - int32 Added = 1 [(gogoproto.jsontag) = ""]; - - // number of lines changed - int32 Changed = 2 [(gogoproto.jsontag) = ""]; - - // number of lines deleted - int32 Deleted = 3 [(gogoproto.jsontag) = ""]; -} - diff --git a/diff/diff_test.go b/diff/diff_test.go index 6ce0571..99400ac 100644 --- a/diff/diff_test.go +++ b/diff/diff_test.go @@ -9,10 +9,14 @@ import ( "testing" "time" - "github.com/shurcooL/go-goon" - "sourcegraph.com/sqs/pbtypes" + "github.com/google/go-cmp/cmp" ) +func unix(sec int64) *time.Time { + t := time.Unix(sec, 0) + return &t +} + func init() { // Diffs include times that by default are generated in the local // timezone. To ensure that tests behave the same in all timezones @@ -47,8 +51,8 @@ func TestParseHunkNoChunksize(t *testing.T) { } h := diff[0] h.Body = nil // We're not testing the body. - if !reflect.DeepEqual(h, correct) { - t.Errorf("%s: Got %#v, want %#v", filename, h, correct) + if !cmp.Equal(h, correct) { + t.Errorf("%s: got - want:\n%s", filename, cmp.Diff(correct, h)) } } @@ -89,7 +93,7 @@ func TestParseHunksAndPrintHunks(t *testing.T) { t.Errorf("%s: PrintHunks: %s", test.filename, err) } if !bytes.Equal(printed, diffData) { - t.Errorf("%s: printed diff hunks != original diff hunks\n\n# PrintHunks output:\n%s\n\n# Original:\n%s", test.filename, printed, diffData) + t.Errorf("%s: printed diff hunks != original diff hunks\n\n# PrintHunks output - Original:\n%s", test.filename, cmp.Diff(diffData, printed)) } } } @@ -103,27 +107,27 @@ func TestParseFileDiffHeaders(t *testing.T) { filename: "sample_file.diff", wantDiff: &FileDiff{ OrigName: "oldname", - OrigTime: &pbtypes.Timestamp{Seconds: 1255273940}, + OrigTime: unix(1255273940), // 2009-10-11 15:12:20 NewName: "newname", - NewTime: &pbtypes.Timestamp{Seconds: 1255273950}, + NewTime: unix(1255273950), // 2009-10-11 15:12:30 }, }, { filename: "sample_file_no_fractional_seconds.diff", wantDiff: &FileDiff{ OrigName: "goyaml.go", - OrigTime: &pbtypes.Timestamp{Seconds: 1322164040}, + OrigTime: unix(1322164040), // 2011-11-24 19:47:20 NewName: "goyaml.go", - NewTime: &pbtypes.Timestamp{Seconds: 1322486679}, + NewTime: unix(1322486679), // 2011-11-28 13:24:39 }, }, { filename: "sample_file_extended.diff", wantDiff: &FileDiff{ OrigName: "oldname", - OrigTime: &pbtypes.Timestamp{Seconds: 1255273940}, + OrigTime: unix(1255273940), // 2009-10-11 15:12:20 NewName: "newname", - NewTime: &pbtypes.Timestamp{Seconds: 1255273950}, + NewTime: unix(1255273950), // 2009-10-11 15:12:30 Extended: []string{ "diff --git a/vcs/git_cmd.go b/vcs/git_cmd.go", "index aa4de15..7c048ab 100644", @@ -228,8 +232,8 @@ func TestParseFileDiffHeaders(t *testing.T) { } diff.Hunks = nil - if got, want := diff, test.wantDiff; !reflect.DeepEqual(got, want) { - t.Errorf("%s:\n\ngot: %v\nwant: %v", test.filename, goon.Sdump(got), goon.Sdump(want)) + if got, want := diff, test.wantDiff; !cmp.Equal(got, want) { + t.Errorf("%s:\n\ngot - want:\n%s", test.filename, cmp.Diff(want, got)) } } } @@ -510,8 +514,8 @@ func TestParseMultiFileDiffHeaders(t *testing.T) { for i := range diffs { diffs[i].Hunks = nil // This test focuses on things other than hunks, so don't compare them. } - if got, want := diffs, test.wantDiffs; !reflect.DeepEqual(got, want) { - t.Errorf("%s:\n\ngot: %v\nwant: %v", test.filename, goon.Sdump(got), goon.Sdump(want)) + if got, want := diffs, test.wantDiffs; !cmp.Equal(got, want) { + t.Errorf("%s:\n\ngot - want:\n%s", test.filename, cmp.Diff(want, got)) } } } @@ -554,7 +558,7 @@ func TestParseFileDiffAndPrintFileDiff(t *testing.T) { t.Errorf("%s: PrintFileDiff: %s", test.filename, err) } if !bytes.Equal(printed, diffData) { - t.Errorf("%s: printed file diff != original file diff\n\n# PrintFileDiff output:\n%s\n\n# Original:\n%s", test.filename, printed, diffData) + t.Errorf("%s: printed file diff != original file diff\n\n# PrintFileDiff output - Original:\n%s", test.filename, cmp.Diff(diffData, printed)) } } } @@ -598,7 +602,7 @@ func TestParseMultiFileDiffAndPrintMultiFileDiff(t *testing.T) { t.Errorf("%s: PrintMultiFileDiff: %s", test.filename, err) } if !bytes.Equal(printed, diffData) { - t.Errorf("%s: printed multi-file diff != original multi-file diff\n\n# PrintMultiFileDiff output:\n%s\n\n# Original:\n%s", test.filename, printed, diffData) + t.Errorf("%s: printed multi-file diff != original multi-file diff\n\n# PrintMultiFileDiff output - Original:\n%s", test.filename, cmp.Diff(diffData, printed)) } } } @@ -659,7 +663,7 @@ func TestNoNewlineAtEnd(t *testing.T) { continue } if printed := string(printed); printed != test.diff { - t.Errorf("%s: printed diff hunks != original diff hunks\n\n# PrintHunks output:\n%s\n\n# Original:\n%s", label, printed, test.diff) + t.Errorf("%s: printed diff hunks != original diff hunks\n\n# PrintHunks output - Original:\n%s", label, cmp.Diff(test.diff, printed)) } } } @@ -718,8 +722,8 @@ func TestFileDiff_Stat(t *testing.T) { for label, test := range tests { fdiff := &FileDiff{Hunks: test.hunks} stat := fdiff.Stat() - if !reflect.DeepEqual(stat, test.want) { - t.Errorf("%s: got diff stat %+v, want %+v", label, stat, test.want) + if !cmp.Equal(stat, test.want) { + t.Errorf("%s: got - want diff stat\n%s", label, cmp.Diff(test.want, stat)) continue } } diff --git a/diff/parse.go b/diff/parse.go index 08cba66..65db17b 100644 --- a/diff/parse.go +++ b/diff/parse.go @@ -9,8 +9,6 @@ import ( "strconv" "strings" "time" - - "sourcegraph.com/sqs/pbtypes" ) // ParseMultiFileDiff parses a multi-file unified diff. It returns an error if @@ -198,12 +196,10 @@ func (r *FileDiffReader) ReadAllHeaders() (*FileDiff, error) { return nil, err } if origTime != nil { - ts := pbtypes.NewTimestamp(*origTime) - fd.OrigTime = &ts + fd.OrigTime = origTime } if newTime != nil { - ts := pbtypes.NewTimestamp(*newTime) - fd.NewTime = &ts + fd.NewTime = newTime } return fd, nil @@ -293,7 +289,7 @@ func (r *FileDiffReader) readOneFileHeader(prefix []byte) (filename string, time type OverflowError string func (e OverflowError) Error() string { - return fmt.Sprintf("overflowed into next file: %s", e) + return fmt.Sprintf("overflowed into next file: %s", string(e)) } // ReadExtendedHeaders reads the extended header lines, if any, from a diff --git a/diff/print.go b/diff/print.go index d440cb9..8dc8caf 100644 --- a/diff/print.go +++ b/diff/print.go @@ -5,8 +5,6 @@ import ( "fmt" "io" "time" - - "sourcegraph.com/sqs/pbtypes" ) // PrintMultiFileDiff prints a multi-file diff in unified diff format. @@ -40,10 +38,10 @@ func PrintFileDiff(d *FileDiff) ([]byte, error) { return buf.Bytes(), nil } - if err := printFileHeader(&buf, "--- ", d.OrigName, timePtr(d.OrigTime)); err != nil { + if err := printFileHeader(&buf, "--- ", d.OrigName, d.OrigTime); err != nil { return nil, err } - if err := printFileHeader(&buf, "+++ ", d.NewName, timePtr(d.NewTime)); err != nil { + if err := printFileHeader(&buf, "+++ ", d.NewName, d.NewTime); err != nil { return nil, err } @@ -58,14 +56,6 @@ func PrintFileDiff(d *FileDiff) ([]byte, error) { return buf.Bytes(), nil } -func timePtr(ts *pbtypes.Timestamp) *time.Time { - if ts == nil { - return nil - } - t := ts.Time() - return &t -} - func printFileHeader(w io.Writer, prefix string, filename string, timestamp *time.Time) error { if _, err := fmt.Fprint(w, prefix, filename); err != nil { return err diff --git a/go.mod b/go.mod index 53843ba..7c43a1d 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,7 @@ module github.com/sourcegraph/go-diff go 1.14 require ( - github.com/gogo/protobuf v1.1.1 + github.com/google/go-cmp v0.5.2 github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e // indirect github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 - sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 ) diff --git a/go.sum b/go.sum index f873681..d618a9a 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ -github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e h1:MZM7FHLqUHYI0Y/mQAt3d2aYa0SiNms/hFqC9qJYolM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041 h1:llrF3Fs4018ePo4+G/HV/uQUqEI1HMDjCeOf2V6puPc= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=