Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache RawData for Commit, Tag, & Tree, fixes #6 #28

Merged
merged 1 commit into from
Dec 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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