Skip to content

Commit

Permalink
Merge pull request #28 from sameer/rawdata
Browse files Browse the repository at this point in the history
Cache RawData for Commit, Tag, & Tree, fixes #6
  • Loading branch information
magik6k authored Dec 30, 2018
2 parents 5b2f4a8 + 0a9e633 commit 705872d
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 57 deletions.
70 changes: 39 additions & 31 deletions commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import (
"errors"
"fmt"
"strconv"
"sync"

cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
)

type Commit struct {
DataSize string `json:"-"`
GitTree cid.Cid `json:"tree"`
Parents []cid.Cid `json:"parents"`
GitTree cid.Cid `json:"tree"`
Parents []cid.Cid `json:"parents"`
Message string `json:"message"`
Author *PersonInfo `json:"author"`
Committer *PersonInfo `json:"committer"`
Expand All @@ -27,6 +28,9 @@ type Commit struct {
Other []string `json:"other,omitempty"`

cid cid.Cid

rawData []byte
rawDataOnce sync.Once
}

type PersonInfo struct {
Expand Down Expand Up @@ -80,7 +84,7 @@ func (pi *PersonInfo) resolve(p []string) (interface{}, []string, error) {
}

type MergeTag struct {
Object cid.Cid `json:"object"`
Object cid.Cid `json:"object"`
Type string `json:"type"`
Tag string `json:"tag"`
Tagger *PersonInfo `json:"tagger"`
Expand Down Expand Up @@ -118,34 +122,38 @@ func (c *Commit) Loggable() map[string]interface{} {
}

func (c *Commit) RawData() []byte {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "commit %s\x00", c.DataSize)
fmt.Fprintf(buf, "tree %s\n", hex.EncodeToString(cidToSha(c.GitTree)))
for _, p := range c.Parents {
fmt.Fprintf(buf, "parent %s\n", hex.EncodeToString(cidToSha(p)))
}
fmt.Fprintf(buf, "author %s\n", c.Author.String())
fmt.Fprintf(buf, "committer %s\n", c.Committer.String())
if len(c.Encoding) > 0 {
fmt.Fprintf(buf, "encoding %s\n", c.Encoding)
}
for _, mtag := range c.MergeTag {
fmt.Fprintf(buf, "mergetag object %s\n", hex.EncodeToString(cidToSha(mtag.Object)))
fmt.Fprintf(buf, " type %s\n", mtag.Type)
fmt.Fprintf(buf, " tag %s\n", mtag.Tag)
fmt.Fprintf(buf, " tagger %s\n \n", mtag.Tagger.String())
fmt.Fprintf(buf, "%s", mtag.Text)
}
if c.Sig != nil {
fmt.Fprintln(buf, "gpgsig -----BEGIN PGP SIGNATURE-----")
fmt.Fprint(buf, c.Sig.Text)
fmt.Fprintln(buf, " -----END PGP SIGNATURE-----")
}
for _, line := range c.Other {
fmt.Fprintln(buf, line)
}
fmt.Fprintf(buf, "\n%s", c.Message)
return buf.Bytes()
c.rawDataOnce.Do(func() {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "commit %s\x00", c.DataSize)
fmt.Fprintf(buf, "tree %s\n", hex.EncodeToString(cidToSha(c.GitTree)))
for _, p := range c.Parents {
fmt.Fprintf(buf, "parent %s\n", hex.EncodeToString(cidToSha(p)))
}
fmt.Fprintf(buf, "author %s\n", c.Author.String())
fmt.Fprintf(buf, "committer %s\n", c.Committer.String())
if len(c.Encoding) > 0 {
fmt.Fprintf(buf, "encoding %s\n", c.Encoding)
}
for _, mtag := range c.MergeTag {
fmt.Fprintf(buf, "mergetag object %s\n", hex.EncodeToString(cidToSha(mtag.Object)))
fmt.Fprintf(buf, " type %s\n", mtag.Type)
fmt.Fprintf(buf, " tag %s\n", mtag.Tag)
fmt.Fprintf(buf, " tagger %s\n \n", mtag.Tagger.String())
fmt.Fprintf(buf, "%s", mtag.Text)
}
if c.Sig != nil {
fmt.Fprintln(buf, "gpgsig -----BEGIN PGP SIGNATURE-----")
fmt.Fprint(buf, c.Sig.Text)
fmt.Fprintln(buf, " -----END PGP SIGNATURE-----")
}
for _, line := range c.Other {
fmt.Fprintln(buf, line)
}
fmt.Fprintf(buf, "\n%s", c.Message)
c.rawData = buf.Bytes()
})

return c.rawData
}

func (c *Commit) Resolve(path []string) (interface{}, []string, error) {
Expand Down
70 changes: 70 additions & 0 deletions git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
"reflect"
"strings"
"testing"

Expand Down Expand Up @@ -171,6 +172,7 @@ func testNode(t *testing.T, nd node.Node) error {

/*s, _ := commit.Size()
assert.Equal(t, len(commit.RawData()), int(s))*/ //TODO: Known breakage
assert(t, reflect.DeepEqual(commit.RawData(), commit.RawData()))
assert(t, commit.GitTree.Defined())
assert(t, commit.Links() != nil)
assert(t, commit.Loggable()["type"] == "git_commit")
Expand Down Expand Up @@ -228,6 +230,7 @@ func testNode(t *testing.T, nd node.Node) error {
}

assert(t, tag.Type == "commit" || tag.Type == "tree" || tag.Type == "blob" || tag.Type == "tag")
assert(t, reflect.DeepEqual(tag.RawData(), tag.RawData()))
assert(t, tag.Object.Defined())
assert(t, tag.Loggable()["type"] == "git_tag")
assert(t, tag.Tree("", -1) != nil)
Expand All @@ -243,6 +246,7 @@ func testNode(t *testing.T, nd node.Node) error {
t.Fatalf("Tree is not a tree")
}

assert(t, reflect.DeepEqual(tree.RawData(), tree.RawData()))
assert(t, tree.entries != nil)
assert(t, tree.Tree("", 0) == nil)
}
Expand Down Expand Up @@ -345,3 +349,69 @@ func assert(t *testing.T, ok bool) {
t.Fatal("Assertion failed")
}
}

func BenchmarkRawData(b *testing.B) {
for i := 0; i < b.N; i++ {
err := filepath.Walk(".git/objects", func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
}
if info.IsDir() {
return nil
}

parts := strings.Split(path, "/")
if dir := parts[len(parts)-2]; dir == "info" || dir == "pack" {
return nil
}

fi, err := os.Open(path)
if err != nil {
return err
}

thing, err := ParseCompressedObject(fi)
if err != nil {
return err
}
thing.RawData()
return nil
})
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkCid(b *testing.B) {
for i := 0; i < b.N; i++ {
err := filepath.Walk(".git/objects", func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil
}
if info.IsDir() {
return nil
}

parts := strings.Split(path, "/")
if dir := parts[len(parts)-2]; dir == "info" || dir == "pack" {
return nil
}

fi, err := os.Open(path)
if err != nil {
return err
}

thing, err := ParseCompressedObject(fi)
if err != nil {
return err
}
thing.Cid()
return nil
})
if err != nil {
b.Fatal(err)
}
}
}
36 changes: 22 additions & 14 deletions tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ package ipldgit
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"sync"

"errors"
cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
)

type Tag struct {
Object cid.Cid `json:"object"`
Object cid.Cid `json:"object"`
Type string `json:"type"`
Tag string `json:"tag"`
Tagger *PersonInfo `json:"tagger"`
Message string `json:"message"`
dataSize string

cid cid.Cid

rawData []byte
rawDataOnce sync.Once
}

func (t *Tag) Cid() cid.Cid {
Expand All @@ -41,18 +45,22 @@ func (t *Tag) Loggable() map[string]interface{} {
}

func (t *Tag) RawData() []byte {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "tag %s\x00", t.dataSize)
fmt.Fprintf(buf, "object %s\n", hex.EncodeToString(cidToSha(t.Object)))
fmt.Fprintf(buf, "type %s\n", t.Type)
fmt.Fprintf(buf, "tag %s\n", t.Tag)
if t.Tagger != nil {
fmt.Fprintf(buf, "tagger %s\n", t.Tagger.String())
}
if t.Message != "" {
fmt.Fprintf(buf, "\n%s", t.Message)
}
return buf.Bytes()
t.rawDataOnce.Do(func() {
buf := new(bytes.Buffer)
fmt.Fprintf(buf, "tag %s\x00", t.dataSize)
fmt.Fprintf(buf, "object %s\n", hex.EncodeToString(cidToSha(t.Object)))
fmt.Fprintf(buf, "type %s\n", t.Type)
fmt.Fprintf(buf, "tag %s\n", t.Tag)
if t.Tagger != nil {
fmt.Fprintf(buf, "tagger %s\n", t.Tagger.String())
}
if t.Message != "" {
fmt.Fprintf(buf, "\n%s", t.Message)
}
t.rawData = buf.Bytes()
})

return t.rawData
}

func (t *Tag) Resolve(path []string) (interface{}, []string, error) {
Expand Down
31 changes: 19 additions & 12 deletions tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,27 @@ package ipldgit
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"sync"

"errors"
cid "github.com/ipfs/go-cid"
node "github.com/ipfs/go-ipld-format"
)

type Tree struct {
entries map[string]*TreeEntry
size int
order []string
cid cid.Cid
entries map[string]*TreeEntry
size int
order []string
cid cid.Cid
rawData []byte
rawDataOnce sync.Once
}

type TreeEntry struct {
name string
Mode string `json:"mode"`
Mode string `json:"mode"`
Hash cid.Cid `json:"hash"`
}

Expand Down Expand Up @@ -95,13 +98,17 @@ func (t *Tree) Loggable() map[string]interface{} {
}

func (t *Tree) RawData() []byte {
buf := new(bytes.Buffer)
t.rawDataOnce.Do(func() {
buf := new(bytes.Buffer)

fmt.Fprintf(buf, "tree %d\x00", t.size)
for _, s := range t.order {
t.entries[s].WriteTo(buf)
}
return buf.Bytes()
fmt.Fprintf(buf, "tree %d\x00", t.size)
for _, s := range t.order {
t.entries[s].WriteTo(buf)
}
t.rawData = buf.Bytes()
})

return t.rawData
}

func (t *Tree) Resolve(p []string) (interface{}, []string, error) {
Expand Down

0 comments on commit 705872d

Please sign in to comment.