Skip to content

Commit

Permalink
sha256: idxfile
Browse files Browse the repository at this point in the history
Signed-off-by: Paulo Gomes <paulo.gomes@suse.com>
  • Loading branch information
pjbgf committed Nov 10, 2023
1 parent a9509b0 commit 8747005
Show file tree
Hide file tree
Showing 24 changed files with 2,502 additions and 41 deletions.
12 changes: 9 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ module github.com/go-git/go-git/v5
// go-git supports the last 3 stable Go versions.
go 1.19

replace github.com/go-git/go-git-fixtures/v4 => ../go-git-fixtures

require (
dario.cat/mergo v1.0.0
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371
Expand All @@ -13,14 +15,15 @@ require (
github.com/gliderlabs/ssh v0.3.5
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231109115935-79c9073c1ec7
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
github.com/google/go-cmp v0.6.0
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
github.com/kevinburke/ssh_config v1.2.0
github.com/pjbgf/sha1cd v0.3.0
github.com/sergi/go-diff v1.1.0
github.com/skeema/knownhosts v1.2.1
github.com/stretchr/testify v1.8.4
github.com/xanzy/ssh-agent v0.3.3
golang.org/x/crypto v0.15.0
golang.org/x/net v0.18.0
Expand All @@ -34,10 +37,13 @@ require (
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/tools v0.13.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/tools v0.15.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
13 changes: 6 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
Expand Down Expand Up @@ -73,6 +71,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand All @@ -86,8 +85,8 @@ golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
Expand All @@ -101,7 +100,7 @@ golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -139,8 +138,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
7 changes: 7 additions & 0 deletions plumbing/format/config/format.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package config

import (
"errors"
)

// RepositoryFormatVersion represents the repository format version,
// as per defined at:
//
Expand Down Expand Up @@ -51,3 +55,6 @@ const (
// DefaultObjectFormat holds the default object format.
DefaultObjectFormat = SHA1
)

// ErrInvalidObjectFormat is returned when an invalid ObjectFormat is used.
var ErrInvalidObjectFormat = errors.New("invalid object format")
231 changes: 231 additions & 0 deletions plumbing/format/idxfile/v3/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
package idxfile

import (
"bufio"
"bytes"
"errors"
"fmt"
"io"

format "github.com/go-git/go-git/v5/plumbing/format/config"
"github.com/go-git/go-git/v5/plumbing/hasher"
"github.com/go-git/go-git/v5/utils/binary"
)

var (
// ErrUnsupportedVersion is returned by Decode when the idx file version
// is not supported.
ErrUnsupportedVersion = errors.New("unsupported version")
// ErrMalformedIdxFile is returned by Decode when the idx file is corrupted.
ErrMalformedIdxFile = errors.New("malformed IDX file")
// ErrMemoryIndexInUse is returned when an exclusive lock cannot be acquired
// for a MemoryIndex. This is likely to happen when the same MemoryIndex is
// being used concurrently for more than one Decode or Encode operation.
ErrMemoryIndexLocked = errors.New("memory index is locked")
)

const (
fanout = 256
magicNumberLength = 4
)

// Decoder reads and decodes idx files from an input stream.
type Decoder struct {
*bufio.Reader
objectFormat format.ObjectFormat
version Version
objectNameLength int
}

// TODO: rename and reuse for encoding? Any specific options that would
// only be for one of those ops?
type DecoderOptions struct {
format.ObjectFormat
}

// NewDecoder builds a new idx stream decoder, that reads from r.
func NewDecoder(r io.Reader) (*Decoder, error) {
return NewDecoderWithOptions(r, DecoderOptions{ObjectFormat: format.SHA1})
}

func NewDecoderWithOptions(r io.Reader, opts DecoderOptions) (*Decoder, error) {
if r == nil {
return nil, fmt.Errorf("cannot create decoder: nil reader")
}

h, err := hasher.FromObjectFormat(opts.ObjectFormat)
if err != nil {
return nil, err
}

return &Decoder{
bufio.NewReader(r),
opts.ObjectFormat,
VersionNotSet,
h.Size(),
}, nil
}

var decodeFlow = []func(*MemoryIndex, io.Reader) error{
readVersion,
readFanout,
readObjectNames,
readCRC32,
readOffsets,
readChecksums,
}

// Decode reads from the stream and decode the content into the MemoryIndex struct.
// It is safe to use a previously used MemoryIndex, as it will be reset before the
// decoding process.
func (d *Decoder) Decode(idx *MemoryIndex) error {
if idx == nil {
return fmt.Errorf("failed to decode: target index is nil")
}

if !idx.m.TryLock() {
return fmt.Errorf("failed to decode: %w", ErrMemoryIndexLocked)
}
defer idx.m.Unlock()
idx.reset(d.objectNameLength, d.objectFormat)

if err := validateHeader(idx, d); err != nil {
return err
}

for _, f := range decodeFlow {
if err := f(idx, d); err != nil {
return err
}
}

return nil
}

func validateHeader(idx *MemoryIndex, r io.Reader) error {
if _, err := io.ReadFull(r, idx.header[:]); err != nil {
return err
}

if !bytes.Equal(idx.header[:], idxHeader) {
return ErrMalformedIdxFile
}

return nil
}

func readVersion(idx *MemoryIndex, r io.Reader) error {
v, err := binary.ReadUint32(r)
if err != nil {
return err
}

switch v {
case uint32(Version2):
idx.Version = 2
case uint32(Version3):
idx.Version = 3
default:
return ErrUnsupportedVersion
}

return nil
}

func readFanout(idx *MemoryIndex, r io.Reader) error {
for k := 0; k < fanout; k++ {
n, err := binary.ReadUint32(r)
if err != nil {
return err
}

idx.Fanout[k] = n
idx.FanoutMapping[k] = noMapping
}

return nil
}

func readObjectNames(idx *MemoryIndex, r io.Reader) error {
for k := 0; k < fanout; k++ {
buckets := idx.Fanout[k]
if k != 0 {
buckets -= idx.Fanout[k-1]
}

if buckets == 0 {
continue
}

idx.FanoutMapping[k] = len(idx.Names)

nameLen := int(buckets) * idx.nameLength
bin := make([]byte, nameLen)
if _, err := io.ReadFull(r, bin); err != nil {
return err
}

idx.Names = append(idx.Names, bin)
idx.Offset32 = append(idx.Offset32, make([]byte, buckets*4))
idx.CRC32 = append(idx.CRC32, make([]byte, buckets*4))
}
return nil
}

func readCRC32(idx *MemoryIndex, r io.Reader) error {
for k := 0; k < fanout; k++ {
if pos := idx.FanoutMapping[k]; pos != noMapping {
if _, err := io.ReadFull(r, idx.CRC32[pos]); err != nil {
return err
}
}
}

return nil
}

func readOffsets(idx *MemoryIndex, r io.Reader) error {
var o64cnt int
for k := 0; k < fanout; k++ {
if pos := idx.FanoutMapping[k]; pos != noMapping {
if _, err := io.ReadFull(r, idx.Offset32[pos]); err != nil {
return err
}

for p := 0; p < len(idx.Offset32[pos]); p += 4 {
if idx.Offset32[pos][p]&(byte(1)<<7) > 0 {
o64cnt++
}
}
}
}

if o64cnt > 0 {
idx.Offset64 = make([]byte, o64cnt*8)
if _, err := io.ReadFull(r, idx.Offset64); err != nil {
return err
}
}

return nil
}

func readChecksums(idx *MemoryIndex, r io.Reader) error {
if len(idx.PackfileChecksum) == 0 {
idx.PackfileChecksum = make([]byte, idx.nameLength)
}

if _, err := io.ReadFull(r, idx.PackfileChecksum[:]); err != nil {
return err
}

if len(idx.IdxChecksum) == 0 {
idx.IdxChecksum = make([]byte, idx.nameLength)
}

if _, err := io.ReadFull(r, idx.IdxChecksum[:]); err != nil {
return err
}

return nil
}
Loading

0 comments on commit 8747005

Please sign in to comment.