From 17f1dfcef77ac30d8db2538b555896e8b7947d6a Mon Sep 17 00:00:00 2001 From: Sameer <11097096+sameer@users.noreply.github.com> Date: Tue, 18 Dec 2018 14:48:19 -0500 Subject: [PATCH] Cache RawData for Commit, Tag, & Tree, fixes #6 --- commit.go | 70 +++++++++++++++++++++++++++++------------------------ git_test.go | 4 +++ tag.go | 36 ++++++++++++++++----------- tree.go | 31 +++++++++++++++--------- 4 files changed, 84 insertions(+), 57 deletions(-) diff --git a/commit.go b/commit.go index c0810c5..ebe2a2f 100644 --- a/commit.go +++ b/commit.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "strconv" + "sync" cid "github.com/ipfs/go-cid" node "github.com/ipfs/go-ipld-format" @@ -14,8 +15,8 @@ import ( 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"` @@ -27,6 +28,9 @@ type Commit struct { Other []string `json:"other,omitempty"` cid cid.Cid + + rawData []byte + rawDataOnce sync.Once } type PersonInfo struct { @@ -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"` @@ -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) { diff --git a/git_test.go b/git_test.go index b0e0b7e..7bf2e4b 100644 --- a/git_test.go +++ b/git_test.go @@ -7,6 +7,7 @@ import ( "io" "os" "path/filepath" + "reflect" "strings" "testing" @@ -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") @@ -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) @@ -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) } diff --git a/tag.go b/tag.go index 4bee947..0655c3d 100644 --- a/tag.go +++ b/tag.go @@ -3,15 +3,16 @@ 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"` @@ -19,6 +20,9 @@ type Tag struct { dataSize string cid cid.Cid + + rawData []byte + rawDataOnce sync.Once } func (t *Tag) Cid() cid.Cid { @@ -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) { diff --git a/tree.go b/tree.go index 5907383..fb49249 100644 --- a/tree.go +++ b/tree.go @@ -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"` } @@ -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) {