aboutsummaryrefslogtreecommitdiffstats
path: root/formats
diff options
context:
space:
mode:
Diffstat (limited to 'formats')
-rw-r--r--formats/idxfile/decoder.go23
-rw-r--r--formats/idxfile/encoder.go24
-rw-r--r--formats/index/decoder.go107
-rw-r--r--formats/packfile/scanner.go126
4 files changed, 56 insertions, 224 deletions
diff --git a/formats/idxfile/decoder.go b/formats/idxfile/decoder.go
index 57b508d..884d32b 100644
--- a/formats/idxfile/decoder.go
+++ b/formats/idxfile/decoder.go
@@ -2,11 +2,11 @@ package idxfile
import (
"bytes"
- "encoding/binary"
"errors"
"io"
"gopkg.in/src-d/go-git.v4/core"
+ "gopkg.in/src-d/go-git.v4/utils/binary"
)
var (
@@ -70,7 +70,7 @@ func validateHeader(r io.Reader) error {
}
func readVersion(idx *Idxfile, r io.Reader) error {
- v, err := readInt32(r)
+ v, err := binary.ReadUint32(r)
if err != nil {
return err
}
@@ -80,21 +80,19 @@ func readVersion(idx *Idxfile, r io.Reader) error {
}
idx.Version = v
-
return nil
}
func readFanout(idx *Idxfile, r io.Reader) error {
var err error
-
for i := 0; i < 255; i++ {
- idx.Fanout[i], err = readInt32(r)
+ idx.Fanout[i], err = binary.ReadUint32(r)
if err != nil {
return err
}
}
- idx.ObjectCount, err = readInt32(r)
+ idx.ObjectCount, err = binary.ReadUint32(r)
return err
}
@@ -115,7 +113,7 @@ func readObjectNames(idx *Idxfile, r io.Reader) error {
func readCRC32(idx *Idxfile, r io.Reader) error {
c := int(idx.ObjectCount)
for i := 0; i < c; i++ {
- if err := binary.Read(r, binary.BigEndian, &idx.Entries[i].CRC32); err != nil {
+ if err := binary.Read(r, &idx.Entries[i].CRC32); err != nil {
return err
}
}
@@ -126,7 +124,7 @@ func readCRC32(idx *Idxfile, r io.Reader) error {
func readOffsets(idx *Idxfile, r io.Reader) error {
c := int(idx.ObjectCount)
for i := 0; i < c; i++ {
- o, err := readInt32(r)
+ o, err := binary.ReadUint32(r)
if err != nil {
return err
}
@@ -148,12 +146,3 @@ func readChecksums(idx *Idxfile, r io.Reader) error {
return nil
}
-
-func readInt32(r io.Reader) (uint32, error) {
- var v uint32
- if err := binary.Read(r, binary.BigEndian, &v); err != nil {
- return 0, err
- }
-
- return v, nil
-}
diff --git a/formats/idxfile/encoder.go b/formats/idxfile/encoder.go
index 0fe9ae6..164414a 100644
--- a/formats/idxfile/encoder.go
+++ b/formats/idxfile/encoder.go
@@ -2,13 +2,11 @@ package idxfile
import (
"crypto/sha1"
- "encoding/binary"
- "fmt"
"hash"
"io"
"sort"
- "gopkg.in/src-d/go-git.v4/core"
+ "gopkg.in/src-d/go-git.v4/utils/binary"
)
// An Encoder writes idx files to an output stream.
@@ -56,13 +54,13 @@ func (e *Encoder) encodeHeader(idx *Idxfile) (int, error) {
return c, err
}
- return c + 4, e.writeInt32(idx.Version)
+ return c + 4, binary.WriteUint32(e, idx.Version)
}
func (e *Encoder) encodeFanout(idx *Idxfile) (int, error) {
fanout := idx.calculateFanout()
for _, c := range fanout {
- if err := e.writeInt32(c); err != nil {
+ if err := binary.WriteUint32(e, c); err != nil {
return 0, err
}
}
@@ -71,31 +69,23 @@ func (e *Encoder) encodeFanout(idx *Idxfile) (int, error) {
}
func (e *Encoder) encodeHashes(idx *Idxfile) (int, error) {
- repet := make(map[core.Hash]int, 0)
-
sz := 0
for _, ent := range idx.Entries {
i, err := e.Write(ent.Hash[:])
sz += i
- repet[ent.Hash]++
if err != nil {
return sz, err
}
}
- for h, c := range repet {
- if c > 1 {
- fmt.Println(h, c)
- }
- }
return sz, nil
}
func (e *Encoder) encodeCRC32(idx *Idxfile) (int, error) {
sz := 0
for _, ent := range idx.Entries {
- err := binary.Write(e, binary.BigEndian, ent.CRC32)
+ err := binary.Write(e, ent.CRC32)
sz += 4
if err != nil {
@@ -109,7 +99,7 @@ func (e *Encoder) encodeCRC32(idx *Idxfile) (int, error) {
func (e *Encoder) encodeOffsets(idx *Idxfile) (int, error) {
sz := 0
for _, ent := range idx.Entries {
- if err := e.writeInt32(uint32(ent.Offset)); err != nil {
+ if err := binary.WriteUint32(e, uint32(ent.Offset)); err != nil {
return sz, err
}
@@ -133,10 +123,6 @@ func (e *Encoder) encodeChecksums(idx *Idxfile) (int, error) {
return 40, nil
}
-func (e *Encoder) writeInt32(value uint32) error {
- return binary.Write(e, binary.BigEndian, value)
-}
-
type EntryList []Entry
func (p EntryList) Len() int { return len(p) }
diff --git a/formats/index/decoder.go b/formats/index/decoder.go
index 9bb25dd..8e37fd1 100644
--- a/formats/index/decoder.go
+++ b/formats/index/decoder.go
@@ -2,7 +2,6 @@ package index
import (
"bytes"
- "encoding/binary"
"errors"
"io"
"io/ioutil"
@@ -10,6 +9,7 @@ import (
"time"
"gopkg.in/src-d/go-git.v4/core"
+ "gopkg.in/src-d/go-git.v4/utils/binary"
)
var (
@@ -50,14 +50,14 @@ func NewDecoder(r io.Reader) *Decoder {
// Decode reads the whole index object from its input and stores it in the
// value pointed to by idx.
func (d *Decoder) Decode(idx *Index) error {
- version, err := validateHeader(d.r)
+ var err error
+ idx.Version, err = validateHeader(d.r)
if err != nil {
return err
}
- idx.Version = version
-
- if err := binary.Read(d.r, binary.BigEndian, &idx.EntryCount); err != nil {
+ idx.EntryCount, err = binary.ReadUint32(d.r)
+ if err != nil {
return err
}
@@ -101,7 +101,7 @@ func (d *Decoder) readEntry(idx *Index) (*Entry, error) {
&e.Flags,
}
- if err := readBinary(d.r, flow...); err != nil {
+ if err := binary.Read(d.r, flow...); err != nil {
return nil, err
}
@@ -111,8 +111,8 @@ func (d *Decoder) readEntry(idx *Index) (*Entry, error) {
e.Stage = Stage(e.Flags>>12) & 0x3
if e.Flags&EntryExtended != 0 {
- var extended uint16
- if err := readBinary(d.r, &extended); err != nil {
+ extended, err := binary.ReadUint16(d.r)
+ if err != nil {
return nil, err
}
@@ -150,7 +150,7 @@ func (d *Decoder) readEntryName(idx *Index, e *Entry) error {
}
func (d *Decoder) doReadEntryNameV4() (string, error) {
- l, err := readVariableWidthInt(d.r)
+ l, err := binary.ReadVariableWidthInt(d.r)
if err != nil {
return "", err
}
@@ -160,7 +160,7 @@ func (d *Decoder) doReadEntryNameV4() (string, error) {
base = d.lastEntry.Name[:len(d.lastEntry.Name)-int(l)]
}
- name, err := readUntil(d.r, '\x00')
+ name, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return "", err
}
@@ -172,7 +172,7 @@ func (d *Decoder) doReadEntryName(e *Entry) (string, error) {
pLen := e.Flags & nameMask
name := make([]byte, int64(pLen))
- if err := binary.Read(d.r, binary.BigEndian, &name); err != nil {
+ if err := binary.Read(d.r, &name); err != nil {
return "", err
}
@@ -217,8 +217,8 @@ func (d *Decoder) readExtension(idx *Index) error {
return err
}
- var len uint32
- if err := binary.Read(d.r, binary.BigEndian, &len); err != nil {
+ len, err := binary.ReadUint32(d.r)
+ if err != nil {
return err
}
@@ -254,7 +254,8 @@ func validateHeader(r io.Reader) (version uint32, err error) {
return 0, ErrMalformedSignature
}
- if err := binary.Read(r, binary.BigEndian, &version); err != nil {
+ version, err = binary.ReadUint32(r)
+ if err != nil {
return 0, err
}
@@ -291,14 +292,14 @@ func (d *treeExtensionDecoder) Decode(t *Tree) error {
func (d *treeExtensionDecoder) readEntry() (*TreeEntry, error) {
e := &TreeEntry{}
- path, err := readUntil(d.r, '\x00')
+ path, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return nil, err
}
e.Path = string(path)
- count, err := readUntil(d.r, ' ')
+ count, err := binary.ReadUntil(d.r, ' ')
if err != nil {
return nil, err
}
@@ -315,7 +316,7 @@ func (d *treeExtensionDecoder) readEntry() (*TreeEntry, error) {
}
e.Entries = i
- trees, err := readUntil(d.r, '\n')
+ trees, err := binary.ReadUntil(d.r, '\n')
if err != nil {
return nil, err
}
@@ -327,7 +328,7 @@ func (d *treeExtensionDecoder) readEntry() (*TreeEntry, error) {
e.Trees = i
- if err := binary.Read(d.r, binary.BigEndian, &e.Hash); err != nil {
+ if err := binary.Read(d.r, &e.Hash); err != nil {
return nil, err
}
@@ -358,7 +359,7 @@ func (d *resolveUndoDecoder) readEntry() (*ResolveUndoEntry, error) {
Stages: make(map[Stage]core.Hash, 0),
}
- path, err := readUntil(d.r, '\x00')
+ path, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return nil, err
}
@@ -373,7 +374,7 @@ func (d *resolveUndoDecoder) readEntry() (*ResolveUndoEntry, error) {
for s := range e.Stages {
var hash core.Hash
- if err := binary.Read(d.r, binary.BigEndian, hash[:]); err != nil {
+ if err := binary.Read(d.r, hash[:]); err != nil {
return nil, err
}
@@ -384,7 +385,7 @@ func (d *resolveUndoDecoder) readEntry() (*ResolveUndoEntry, error) {
}
func (d *resolveUndoDecoder) readStage(e *ResolveUndoEntry, s Stage) error {
- ascii, err := readUntil(d.r, '\x00')
+ ascii, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return err
}
@@ -400,67 +401,3 @@ func (d *resolveUndoDecoder) readStage(e *ResolveUndoEntry, s Stage) error {
return nil
}
-
-func readBinary(r io.Reader, data ...interface{}) error {
- for _, v := range data {
- err := binary.Read(r, binary.BigEndian, v)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func readUntil(r io.Reader, delim byte) ([]byte, error) {
- var buf [1]byte
- value := make([]byte, 0, 16)
- for {
- if _, err := r.Read(buf[:]); err != nil {
- if err == io.EOF {
- return nil, err
- }
-
- return nil, err
- }
-
- if buf[0] == delim {
- return value, nil
- }
-
- value = append(value, buf[0])
- }
-}
-
-// dheader[pos] = ofs & 127;
-// while (ofs >>= 7)
-// dheader[--pos] = 128 | (--ofs & 127);
-//
-func readVariableWidthInt(r io.Reader) (int64, error) {
- var c byte
- if err := readBinary(r, &c); err != nil {
- return 0, err
- }
-
- var v = int64(c & maskLength)
- for moreBytesInLength(c) {
- v++
- if err := readBinary(r, &c); err != nil {
- return 0, err
- }
-
- v = (v << lengthBits) + int64(c&maskLength)
- }
-
- return v, nil
-}
-
-const (
- maskContinue = uint8(128) // 1000 000
- maskLength = uint8(127) // 0111 1111
- lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
-)
-
-func moreBytesInLength(c byte) bool {
- return c&maskContinue > 0
-}
diff --git a/formats/packfile/scanner.go b/formats/packfile/scanner.go
index a5e4215..69cc7d0 100644
--- a/formats/packfile/scanner.go
+++ b/formats/packfile/scanner.go
@@ -4,7 +4,6 @@ import (
"bufio"
"bytes"
"compress/zlib"
- "encoding/binary"
"fmt"
"hash"
"hash/crc32"
@@ -12,6 +11,7 @@ import (
"io/ioutil"
"gopkg.in/src-d/go-git.v4/core"
+ "gopkg.in/src-d/go-git.v4/utils/binary"
)
var (
@@ -129,7 +129,7 @@ func (s *Scanner) isValidSignature(sig []byte) bool {
// readVersion reads and returns the version field of a packfile.
func (s *Scanner) readVersion() (uint32, error) {
- return s.readInt32()
+ return binary.ReadUint32(s.r)
}
// isSupportedVersion returns whether version v is supported by the parser.
@@ -140,17 +140,7 @@ func (s *Scanner) isSupportedVersion(v uint32) bool {
// readCount reads and returns the count of objects field of a packfile.
func (s *Scanner) readCount() (uint32, error) {
- return s.readInt32()
-}
-
-// ReadInt32 reads 4 bytes and returns them as a Big Endian int32.
-func (s *Scanner) readInt32() (uint32, error) {
- var v uint32
- if err := binary.Read(s.r, binary.BigEndian, &v); err != nil {
- return 0, err
- }
-
- return v, nil
+ return binary.ReadUint32(s.r)
}
// NextObjectHeader returns the ObjectHeader for the next object in the reader
@@ -177,15 +167,15 @@ func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) {
switch h.Type {
case core.OFSDeltaObject:
- no, err := s.readNegativeOffset()
+ no, err := binary.ReadVariableWidthInt(s.r)
if err != nil {
return nil, err
}
- h.OffsetReference = h.Offset + no
+ h.OffsetReference = h.Offset - no
case core.REFDeltaObject:
var err error
- h.Reference, err = s.readHash()
+ h.Reference, err = binary.ReadHash(s.r)
if err != nil {
return nil, err
}
@@ -240,10 +230,19 @@ func (s *Scanner) readObjectTypeAndLength() (core.ObjectType, int64, error) {
return t, l, err
}
+const (
+ maskType = uint8(112) // 0111 0000
+ maskFirstLength = uint8(15) // 0000 1111
+ maskContinue = uint8(128) // 1000 000
+ firstLengthBits = uint8(4) // the first byte has 4 bits to store the length
+ maskLength = uint8(127) // 0111 1111
+ lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
+)
+
func (s *Scanner) readType() (core.ObjectType, byte, error) {
var c byte
var err error
- if c, err = s.readByte(); err != nil {
+ if c, err = s.r.ReadByte(); err != nil {
return core.ObjectType(0), 0, err
}
@@ -252,6 +251,10 @@ func (s *Scanner) readType() (core.ObjectType, byte, error) {
return typ, c, nil
}
+func parseType(b byte) core.ObjectType {
+ return core.ObjectType((b & maskType) >> firstLengthBits)
+}
+
// the length is codified in the last 4 bits of the first byte and in
// the last 7 bits of subsequent bytes. Last byte has a 0 MSB.
func (s *Scanner) readLength(first byte) (int64, error) {
@@ -260,8 +263,8 @@ func (s *Scanner) readLength(first byte) (int64, error) {
c := first
shift := firstLengthBits
var err error
- for moreBytesInLength(c) {
- if c, err = s.readByte(); err != nil {
+ for c&maskContinue > 0 {
+ if c, err = s.r.ReadByte(); err != nil {
return 0, err
}
@@ -324,73 +327,7 @@ func (s *Scanner) Checksum() (core.Hash, error) {
return core.ZeroHash, err
}
- return s.readHash()
-}
-
-// ReadHash reads a hash.
-func (s *Scanner) readHash() (core.Hash, error) {
- var h core.Hash
- if _, err := io.ReadFull(s.r, h[:]); err != nil {
- return core.ZeroHash, err
- }
-
- return h, nil
-}
-
-// ReadNegativeOffset reads and returns an offset from a OFS DELTA
-// object entry in a packfile. OFS DELTA offsets are specified in Git
-// VLQ special format:
-//
-// Ordinary VLQ has some redundancies, example: the number 358 can be
-// encoded as the 2-octet VLQ 0x8166 or the 3-octet VLQ 0x808166 or the
-// 4-octet VLQ 0x80808166 and so forth.
-//
-// To avoid these redundancies, the VLQ format used in Git removes this
-// prepending redundancy and extends the representable range of shorter
-// VLQs by adding an offset to VLQs of 2 or more octets in such a way
-// that the lowest possible value for such an (N+1)-octet VLQ becomes
-// exactly one more than the maximum possible value for an N-octet VLQ.
-// In particular, since a 1-octet VLQ can store a maximum value of 127,
-// the minimum 2-octet VLQ (0x8000) is assigned the value 128 instead of
-// 0. Conversely, the maximum value of such a 2-octet VLQ (0xff7f) is
-// 16511 instead of just 16383. Similarly, the minimum 3-octet VLQ
-// (0x808000) has a value of 16512 instead of zero, which means
-// that the maximum 3-octet VLQ (0xffff7f) is 2113663 instead of
-// just 2097151. And so forth.
-//
-// This is how the offset is saved in C:
-//
-// dheader[pos] = ofs & 127;
-// while (ofs >>= 7)
-// dheader[--pos] = 128 | (--ofs & 127);
-//
-func (s *Scanner) readNegativeOffset() (int64, error) {
- var c byte
- var err error
-
- if c, err = s.readByte(); err != nil {
- return 0, err
- }
-
- var offset = int64(c & maskLength)
- for moreBytesInLength(c) {
- offset++
- if c, err = s.readByte(); err != nil {
- return 0, err
- }
- offset = (offset << lengthBits) + int64(c&maskLength)
- }
-
- return -offset, nil
-}
-
-func (s *Scanner) readByte() (byte, error) {
- b, err := s.r.ReadByte()
- if err != nil {
- return 0, err
- }
-
- return b, err
+ return binary.ReadHash(s.r)
}
// Close reads the reader until io.EOF
@@ -399,23 +336,6 @@ func (s *Scanner) Close() error {
return err
}
-func moreBytesInLength(c byte) bool {
- return c&maskContinue > 0
-}
-
-var (
- maskContinue = uint8(128) // 1000 0000
- maskType = uint8(112) // 0111 0000
- maskFirstLength = uint8(15) // 0000 1111
- firstLengthBits = uint8(4) // the first byte has 4 bits to store the length
- maskLength = uint8(127) // 0111 1111
- lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
-)
-
-func parseType(b byte) core.ObjectType {
- return core.ObjectType((b & maskType) >> firstLengthBits)
-}
-
type trackableReader struct {
count int64
io.Reader