diff --git a/git/odb/object_db.go b/git/odb/object_db.go index 51cca9e2..5f74045c 100644 --- a/git/odb/object_db.go +++ b/git/odb/object_db.go @@ -42,6 +42,17 @@ func (o *ObjectDatabase) Tree(sha []byte) (*Tree, error) { return &t, nil } +// Commit returns a *Commit as identified by the SHA given, or an error if one +// was encountered. +func (o *ObjectDatabase) Commit(sha []byte) (*Commit, error) { + var c Commit + + if err := o.decode(sha, &c); err != nil { + return nil, err + } + return &c, nil +} + // WriteBlob stores a *Blob on disk and returns the SHA it is uniquely // identified by, or an error if one was encountered. func (o *ObjectDatabase) WriteBlob(b *Blob) ([]byte, error) { @@ -68,6 +79,16 @@ func (o *ObjectDatabase) WriteTree(t *Tree) ([]byte, error) { return sha, nil } +// WriteCommit stores a *Commit on disk and returns the SHA it is uniquely +// identified by, or an error if one was encountered. +func (o *ObjectDatabase) WriteCommit(c *Commit) ([]byte, error) { + sha, _, err := o.encode(c) + if err != nil { + return nil, err + } + return sha, nil +} + // encode encodes and saves an object to the storage backend and uses an // in-memory buffer to calculate the object's encoded body. func (d *ObjectDatabase) encode(object Object) (sha []byte, n int, err error) { diff --git a/git/odb/object_db_test.go b/git/odb/object_db_test.go index 1f3eda4d..c22b1ff0 100644 --- a/git/odb/object_db_test.go +++ b/git/odb/object_db_test.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -72,6 +73,37 @@ func TestDecodeTree(t *testing.T) { }, tree.Entries[0]) } +func TestDecodeCommit(t *testing.T) { + sha := "d7283480bb6dc90be621252e1001a93871dcf511" + commitShaHex, err := hex.DecodeString(sha) + assert.Nil(t, err) + + var buf bytes.Buffer + + zw := zlib.NewWriter(&buf) + fmt.Fprintf(zw, "commit 173\x00") + fmt.Fprintf(zw, "tree fcb545d5746547a597811b7441ed8eba307be1ff\n") + fmt.Fprintf(zw, "author Taylor Blau 1494620424 -0600\n") + fmt.Fprintf(zw, "committer Taylor Blau 1494620424 -0600\n") + fmt.Fprintf(zw, "\ninitial commit\n") + zw.Close() + + odb := &ObjectDatabase{s: NewMemoryStorer(map[string]io.ReadWriter{ + sha: &buf, + })} + + commit, err := odb.Commit(commitShaHex) + + assert.Nil(t, err) + assert.Equal(t, "Taylor Blau", commit.Author.Name) + assert.Equal(t, "me@ttaylorr.com", commit.Author.Email) + assert.Equal(t, "Taylor Blau", commit.Committer.Name) + assert.Equal(t, "me@ttaylorr.com", commit.Committer.Email) + assert.Equal(t, "initial commit", commit.Message) + assert.Equal(t, 0, len(commit.ParentIds)) + assert.Equal(t, "fcb545d5746547a597811b7441ed8eba307be1ff", hex.EncodeToString(commit.TreeId)) +} + func TestWriteBlob(t *testing.T) { fs := NewMemoryStorer(make(map[string]io.ReadWriter)) odb := &ObjectDatabase{s: fs} @@ -111,3 +143,29 @@ func TestWriteTree(t *testing.T) { assert.Equal(t, expected, hex.EncodeToString(sha)) assert.NotNil(t, fs.fs[hex.EncodeToString(sha)]) } + +func TestWriteCommit(t *testing.T) { + fs := NewMemoryStorer(make(map[string]io.ReadWriter)) + odb := &ObjectDatabase{s: fs} + + when := time.Unix(1494258422, 0) + author := &Signature{Name: "John Doe", Email: "john@example.com", When: when} + committer := &Signature{Name: "Jane Doe", Email: "jane@example.com", When: when} + + tree := "fcb545d5746547a597811b7441ed8eba307be1ff" + treeHex, err := hex.DecodeString(tree) + assert.Nil(t, err) + + sha, err := odb.WriteCommit(&Commit{ + Author: author, + Committer: committer, + TreeId: treeHex, + Message: "initial commit", + }) + + expected := "5ba51ea684770de6fef57a94734c4f4a02cb361b" + + assert.Nil(t, err) + assert.Equal(t, expected, hex.EncodeToString(sha)) + assert.NotNil(t, fs.fs[hex.EncodeToString(sha)]) +}