Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit d2d68d3

Browse files
committed
format: packfile based on ObjectStorage and CRC32 calculation
1 parent 96d5f5f commit d2d68d3

22 files changed

+531
-739
lines changed

common_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ func unpackFixtures(c *C, fixtures ...[]packedFixture) map[string]*Repository {
126126
d := packfile.NewDecoder(r, repos[fixture.url].s.ObjectStorage())
127127
_, err = d.Decode()
128128
c.Assert(err, IsNil, comment)
129-
130129
c.Assert(f.Close(), IsNil, comment)
131130
}
132131
}

core/storage.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type ObjectIter interface {
5454
// A transaction must end with a call to Commit or Rollback.
5555
type TxObjectStorage interface {
5656
Set(Object) (Hash, error)
57+
Get(ObjectType, Hash) (Object, error)
5758
Commit() error
5859
Rollback() error
5960
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

fixtures/fixtures.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package fixtures
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"os"
7+
"path/filepath"
8+
9+
check "gopkg.in/check.v1"
10+
"gopkg.in/src-d/go-git.v4/core"
11+
)
12+
13+
var RootFolder = ""
14+
15+
const DataFolder = "data"
16+
17+
var fixtures = []*Fixture{{
18+
Tags: []string{"ofs-delta"},
19+
URL: "https://github.com/git-fixtures/basic",
20+
Head: core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"),
21+
PackfileHash: core.NewHash("a3fed42da1e8189a077c0e6846c040dcf73fc9dd"),
22+
}, {
23+
Tags: []string{"ref-delta"},
24+
URL: "https://github.com/git-fixtures/basic",
25+
Head: core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"),
26+
PackfileHash: core.NewHash("c544593473465e6315ad4182d04d366c4592b829"),
27+
}, {
28+
URL: "https://github.com/spinnaker/spinnaker",
29+
Head: core.NewHash("06ce06d0fc49646c4de733c45b7788aabad98a6f"),
30+
PackfileHash: core.NewHash("f2e0a8889a746f7600e07d2246a2e29a72f696be"),
31+
}}
32+
33+
func All() Fixtures {
34+
return fixtures
35+
}
36+
37+
func Basic() Fixtures {
38+
return ByURL("https://github.com/git-fixtures/basic")
39+
}
40+
41+
func ByURL(url string) Fixtures {
42+
r := make(Fixtures, 0)
43+
for _, f := range fixtures {
44+
if f.URL == url {
45+
r = append(r, f)
46+
}
47+
}
48+
49+
return r
50+
}
51+
52+
type Fixture struct {
53+
URL string
54+
Tags []string
55+
Head core.Hash
56+
PackfileHash core.Hash
57+
}
58+
59+
func (f *Fixture) Packfile() io.ReadSeeker {
60+
fn := filepath.Join(RootFolder, DataFolder, fmt.Sprintf("pack-%s.pack", f.PackfileHash))
61+
file, err := os.Open(fn)
62+
if err != nil {
63+
panic(err)
64+
}
65+
66+
return file
67+
}
68+
69+
func (f *Fixture) Idx() io.ReadSeeker {
70+
fn := filepath.Join(RootFolder, DataFolder, fmt.Sprintf("pack-%s.idx", f.PackfileHash))
71+
file, err := os.Open(fn)
72+
if err != nil {
73+
panic(err)
74+
}
75+
76+
return file
77+
}
78+
79+
type Fixtures []*Fixture
80+
81+
func (g Fixtures) Test(c *check.C, test func(*Fixture)) {
82+
for _, f := range g {
83+
c.Logf("executing test at %s", f.URL)
84+
test(f)
85+
}
86+
}
87+
88+
func (g Fixtures) One() *Fixture {
89+
return g[0]
90+
}
91+
92+
func (g Fixtures) ByTag(tag string) *Fixture {
93+
for _, f := range g {
94+
for _, t := range f.Tags {
95+
if t == tag {
96+
return f
97+
}
98+
}
99+
}
100+
101+
return nil
102+
}

formats/idxfile/decoder.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"encoding/binary"
66
"errors"
7+
"fmt"
78
"io"
89

910
"gopkg.in/src-d/go-git.v4/core"
@@ -95,7 +96,7 @@ func readFanout(idx *Idxfile, r io.Reader) error {
9596
}
9697

9798
idx.ObjectCount, err = readInt32(r)
98-
99+
fmt.Println(idx.ObjectCount)
99100
return err
100101
}
101102

@@ -116,7 +117,7 @@ func readObjectNames(idx *Idxfile, r io.Reader) error {
116117
func readCRC32(idx *Idxfile, r io.Reader) error {
117118
c := int(idx.ObjectCount)
118119
for i := 0; i < c; i++ {
119-
if _, err := r.Read(idx.Entries[i].CRC32[:]); err != nil {
120+
if err := binary.Read(r, binary.BigEndian, &idx.Entries[i].CRC32); err != nil {
120121
return err
121122
}
122123
}

formats/idxfile/decoder_test.go

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package idxfile
22

33
import (
4+
"bytes"
45
"fmt"
5-
"os"
66
"testing"
77

88
. "gopkg.in/check.v1"
9+
"gopkg.in/src-d/go-git.v4/fixtures"
10+
"gopkg.in/src-d/go-git.v4/formats/packfile"
11+
"gopkg.in/src-d/go-git.v4/storage/memory"
912
)
1013

1114
func Test(t *testing.T) { TestingT(t) }
@@ -15,26 +18,50 @@ type IdxfileSuite struct{}
1518
var _ = Suite(&IdxfileSuite{})
1619

1720
func (s *IdxfileSuite) TestDecode(c *C) {
18-
f, err := os.Open("fixtures/git-fixture.idx")
19-
c.Assert(err, IsNil)
21+
f := fixtures.Basic().One()
2022

21-
d := NewDecoder(f)
23+
d := NewDecoder(f.Idx())
2224
idx := &Idxfile{}
23-
err = d.Decode(idx)
25+
err := d.Decode(idx)
2426
c.Assert(err, IsNil)
2527

26-
err = f.Close()
27-
c.Assert(err, IsNil)
28-
29-
c.Assert(int(idx.ObjectCount), Equals, 31)
3028
c.Assert(idx.Entries, HasLen, 31)
31-
c.Assert(idx.Entries[0].Hash.String(), Equals,
32-
"1669dce138d9b841a518c64b10914d88f5e488ea")
29+
c.Assert(idx.Entries[0].Hash.String(), Equals, "1669dce138d9b841a518c64b10914d88f5e488ea")
3330
c.Assert(idx.Entries[0].Offset, Equals, uint64(615))
31+
c.Assert(idx.Entries[0].CRC32, Equals, uint32(3645019190))
32+
33+
c.Assert(fmt.Sprintf("%x", idx.IdxChecksum), Equals, "fb794f1ec720b9bc8e43257451bd99c4be6fa1c9")
34+
c.Assert(fmt.Sprintf("%x", idx.PackfileChecksum), Equals, f.PackfileHash.String())
35+
}
36+
37+
func (s *IdxfileSuite) TestDecodeCRCs(c *C) {
38+
f := fixtures.Basic().ByTag("ofs-delta")
39+
40+
scanner := packfile.NewScanner(f.Packfile())
41+
storage := memory.NewStorage()
42+
43+
pd := packfile.NewDecoder(scanner, storage.ObjectStorage())
44+
checksum, err := pd.Decode()
45+
c.Assert(err, IsNil)
46+
47+
i := &Idxfile{Version: VersionSupported}
48+
i.PackfileChecksum = checksum
49+
50+
offsets := pd.Offsets()
51+
for h, crc := range pd.CRCs() {
52+
i.Add(h, uint64(offsets[h]), crc)
53+
}
54+
55+
buf := bytes.NewBuffer(nil)
56+
e := NewEncoder(buf)
57+
_, err = e.Encode(i)
58+
c.Assert(err, IsNil)
3459

35-
c.Assert(fmt.Sprintf("%x", idx.IdxChecksum), Equals,
36-
"bba9b7a9895724819225a044c857d391bb9d61d9")
37-
c.Assert(fmt.Sprintf("%x", idx.PackfileChecksum), Equals,
38-
"54bb61360ab2dad1a3e344a8cd3f82b848518cba")
60+
idx := &Idxfile{}
61+
62+
d := NewDecoder(buf)
63+
err = d.Decode(idx)
64+
c.Assert(err, IsNil)
3965

66+
c.Assert(idx, DeepEquals, i)
4067
}

formats/idxfile/encoder.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,24 @@ func (e *Encoder) encodeFanout(idx *Idxfile) (int, error) {
6565
}
6666

6767
func (e *Encoder) encodeHashes(idx *Idxfile) (int, error) {
68-
return e.encodeEntryField(idx, true)
69-
}
68+
sz := 0
69+
for _, ent := range idx.Entries {
70+
i, err := e.Write(ent.Hash[:])
71+
sz += i
7072

71-
func (e *Encoder) encodeCRC32(idx *Idxfile) (int, error) {
72-
return e.encodeEntryField(idx, false)
73+
if err != nil {
74+
return sz, err
75+
}
76+
}
77+
78+
return sz, nil
7379
}
7480

75-
func (e *Encoder) encodeEntryField(idx *Idxfile, isHash bool) (int, error) {
81+
func (e *Encoder) encodeCRC32(idx *Idxfile) (int, error) {
7682
sz := 0
7783
for _, ent := range idx.Entries {
78-
var data []byte
79-
if isHash {
80-
data = ent.Hash[:]
81-
} else {
82-
data = ent.CRC32[:]
83-
}
84-
85-
i, err := e.Write(data)
86-
sz += i
84+
err := binary.Write(e, binary.BigEndian, ent.CRC32)
85+
sz += 4
8786

8887
if err != nil {
8988
return sz, err

formats/idxfile/encoder_test.go

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,32 @@ package idxfile
22

33
import (
44
"bytes"
5-
"io"
6-
"os"
5+
"io/ioutil"
76

87
. "gopkg.in/check.v1"
8+
"gopkg.in/src-d/go-git.v4/fixtures"
99
)
1010

11-
func (s *IdxfileSuite) TestEncode(c *C) {
12-
for i, path := range [...]string{
13-
"fixtures/git-fixture.idx",
14-
"../packfile/fixtures/spinnaker-spinnaker.idx",
15-
} {
16-
com := Commentf("subtest %d: path = %s", i, path)
17-
18-
exp, idx, err := decode(path)
19-
c.Assert(err, IsNil, com)
20-
21-
obt := new(bytes.Buffer)
22-
e := NewEncoder(obt)
23-
size, err := e.Encode(idx)
24-
c.Assert(err, IsNil, com)
25-
26-
c.Assert(size, Equals, exp.Len(), com)
27-
c.Assert(obt, DeepEquals, exp, com)
28-
}
11+
func (s *IdxfileSuite) SetUpSuite(c *C) {
12+
fixtures.RootFolder = "../../fixtures"
2913
}
3014

31-
func decode(path string) (*bytes.Buffer, *Idxfile, error) {
32-
f, err := os.Open(path)
33-
if err != nil {
34-
return nil, nil, err
35-
}
15+
func (s *IdxfileSuite) TestEncode(c *C) {
16+
fixtures.All().Test(c, func(f *fixtures.Fixture) {
17+
expected, err := ioutil.ReadAll(f.Idx())
18+
c.Assert(err, IsNil)
3619

37-
cont := new(bytes.Buffer)
38-
tee := io.TeeReader(f, cont)
20+
idx := &Idxfile{}
21+
d := NewDecoder(bytes.NewBuffer(expected))
22+
err = d.Decode(idx)
23+
c.Assert(err, IsNil)
3924

40-
d := NewDecoder(tee)
41-
idx := &Idxfile{}
42-
if err = d.Decode(idx); err != nil {
43-
return nil, nil, err
44-
}
25+
result := bytes.NewBuffer(nil)
26+
e := NewEncoder(result)
27+
size, err := e.Encode(idx)
28+
c.Assert(err, IsNil)
4529

46-
return cont, idx, f.Close()
30+
c.Assert(size, Equals, len(expected))
31+
c.Assert(result.Bytes(), DeepEquals, expected)
32+
})
4733
}

formats/idxfile/idxfile.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,18 @@ type Idxfile struct {
2525
// offset and CRC32 checksum.
2626
type Entry struct {
2727
Hash core.Hash
28-
CRC32 [4]byte
28+
CRC32 uint32
2929
Offset uint64
3030
}
3131

32+
func (idx *Idxfile) Add(h core.Hash, offset uint64, crc32 uint32) {
33+
idx.Entries = append(idx.Entries, Entry{
34+
Hash: h,
35+
Offset: offset,
36+
CRC32: crc32,
37+
})
38+
}
39+
3240
func (idx *Idxfile) isValid() bool {
3341
fanout := idx.calculateFanout()
3442
for k, c := range idx.Fanout {

0 commit comments

Comments
 (0)